sun-pc-linux 3 روز پیش
والد
کامیت
7ccb506ba7

+ 82 - 65
src/api/api.http

@@ -1,20 +1,55 @@
-@host = 192.168.110.131:8085/nrhe
+@host = 192.168.110.131:8086/moutai
 
 
-###
-# 用户管理
+# 角色管理
+
+### 
+# 新增角色
+POST http://{{host}}/admin/role/create HTTP/1.1
+Content-Type: application/json
+Authorization: Bearer xxx
+
+{
+    "name": "管理员"
+}
+
+### 
+# 删除角色
+POST http://{{host}}/admin/role/delete/:id HTTP/1.1
+Content-Type: application/json
+Authorization: Bearer xxx
 
 
 ### 
-# 登录
+# 角色列表
+GET http://{{host}}/admin/role/list HTTP/1.1
+Content-Type: application/json
+Authorization: Bearer xxx
+
+### 
+# 更新角色
+GET http://{{host}}/admin/role/update HTTP/1.1
+Content-Type: application/json
+Authorization: Bearer xxx
+
+{
+	"_id": "xxx",
+    "name": "管理员"
+}
+
+
+
+# 用户管理
+
+### 
+# 用户登录
 POST http://{{host}}/user/login/password HTTP/1.1
 Content-Type: application/json
 Authorization: Bearer xxx
 
 {
     "loginName": "zhangsan",
-    "password": "123456",
-    "role": "student"
+    "password": "123456"
 }
 
 ### 
@@ -24,11 +59,11 @@ Content-Type: application/json
 Authorization: Bearer xxx
 
 {
-    "nid": "昵称",
+    "name": "名字",
     "loginName": "xxx",
     "password": "xxx",
     "avatar": "xxx.png",
-    "roles": ["admin/student"]
+    "roleId": "xxx"
 }
 
 ### 
@@ -44,17 +79,12 @@ POST http://{{host}}/admin/user/delete/:id HTTP/1.1
 Content-Type: application/json
 Authorization: Bearer xxx
 
-
 ### 
-# 批量删除用户
-POST http://{{host}}/admin/user/delete/batch HTTP/1.1
+# 禁用用户
+POST http://{{host}}/admin/user/disable/:id HTTP/1.1
 Content-Type: application/json
 Authorization: Bearer xxx
 
-{
-    "ids": ["xxx","xxx"]
-}
-
 
 ### 
 # 用户列表
@@ -70,80 +100,67 @@ Authorization: Bearer xxx
 
 {
     "_id": "xxx",
-    "nid": "昵称",
+    "name": "名字",
     "loginName": "xxx",
     "password": "xxx",
     "avatar": "xxx.png",
-    "roles": ["admin/student"]
+    "roleId": "xxx"
 }
 
+# 分类管理
 
 ### 
-# 导出用户
-GET http://{{host}}/admin/user/export HTTP/1.1
+# 新增分类
+POST http://{{host}}/admin/cate/create HTTP/1.1
 Content-Type: application/json
 Authorization: Bearer xxx
 
+{
+    "name": "xxx",
+    "type": "xxx",
+}
 
 ### 
-# 导入用户
-# 上传文件名为file
-POST http://{{host}}/admin/user/import HTTP/1.1
+# 删除分类
+POST http://{{host}}/admin/cate/delete/:id HTTP/1.1
 Content-Type: application/json
 Authorization: Bearer xxx
 
 
 ### 
-# 下载模板
-GET http://{{host}}/admin/user/tmplate HTTP/1.1
+# 分类列表
+GET http://{{host}}/admin/cate/list HTTP/1.1
 Content-Type: application/json
 Authorization: Bearer xxx
 
-
-###
-# 创建考核记录
-POST http://{{host}}/exam/history/create HTTP/1.1
+### 
+# 更新分类
+GET http://{{host}}/admin/cate/update HTTP/1.1
 Content-Type: application/json
-Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzI1OTAwMDgsImlkIjoiNjczYmZjY2E3MjQyNWIxOGQxMmMyMzk0Iiwib3JpZ19pYXQiOjE3MzE5ODUyMDh9.PkGZwgFVONilDTPQ6f_Gc5t6NlbdC1DGiaScQtU_-2A
-
+Authorization: Bearer xxx
 
 {
-	"produceName": "英语词汇测试",
-	"examRecord": [
-		{
-			"title": "单词拼写:Apple",
-			"result": "正确",
-			"isCorrect": true
-		},
-		{
-			"title": "单词拼写:Banana",
-			"result": "错误",
-			"isCorrect": false
-		},
-		{
-			"title": "单词拼写:Cat",
-			"result": "正确",
-			"isCorrect": true
-		},
-		{
-			"title": "单词拼写:Dog",
-			"result": "正确",
-			"isCorrect": true
-		},
-		{
-			"title": "单词拼写:Elephant",
-			"result": "错误",
-			"isCorrect": false
-		}
-	],
-	"totalScore": 85,
-	"correct": 13,
-	"mistake": 2
+	"_id": "xxx",
+    "name": "管理员",
+    "type": "xx"
 }
 
-###
-# 查询考核历史,如果query中没有userId则查询当前登录用户的
-GET http://{{host}}/exam/history/list?page=1&size=10&query={"userId": "xxx"} HTTP/1.1
+
+# 首页内容
+
+### 
+# 首页内容详情
+POST http://{{host}}/admin/home/detail HTTP/1.1
 Content-Type: application/json
-Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MjI4MjU4OTIsImlkIjoiNjQyYTUyNGY1ZjUwYmM5MDNmOTg2Mzk0Iiwia2V5IjoiYm94Y29zdCIsIm5hbWUiOiLlrZnog5wiLCJvcmlnX2lhdCI6MTcyMjIyMTA5MiwicGFyZW50IjoiNjQyYTUyNGY1ZjUwYmM5MDNmOTg2Mzk0IiwicGhvbmUiOiIxMzQwODU0NzgyMyIsInJvbGUiOiIiLCJzdGF0ZSI6MSwidXNlclR5cGUiOjJ9.Cz7qI3-Vah0io5ZLIFDyVOf8qsqdmbT8WHdprrjbdXw
+Authorization: Bearer xxx
+
 
+### 
+# 首页内容发布
+POST http://{{host}}/admin/home/content HTTP/1.1
+Content-Type: application/json
+Authorization: Bearer xxx
+
+{
+    "content": "xxxx"
+}

+ 133 - 0
src/api/ar.go

@@ -0,0 +1,133 @@
+package api
+
+import (
+	"errors"
+	"moutai/db/model"
+	"moutai/db/repo"
+	"moutai/log"
+	"strconv"
+	"time"
+
+	"github.com/gin-gonic/gin"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+func CreateAr(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	Ar := &model.Ar{}
+	err := c.ShouldBindJSON(&Ar)
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+
+	// 正常状态
+	state := -1
+	Ar.State = &state
+	Ar.CreateTime = time.Now()
+	Ar.UpdateTime = time.Now()
+	return repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionAr, &Ar)
+}
+
+func DeleteAr(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	return repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionAr, _id)
+}
+
+func ArList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	page, size, query := UtilQueryPageSize(c)
+	_uploadTime := c.Query("uploadTime")
+	_cid := c.Query("cid")
+	cid, _ := primitive.ObjectIDFromHex(_cid)
+	name := c.Query("name")
+	_sort := c.Query("sort")
+	sortInt, _ := strconv.Atoi(_sort)
+	sort := repo.Map{"createTime": -1}
+	if sortInt > 0 {
+		sort = repo.Map{"sort": -1}
+	}
+
+	if !cid.IsZero() {
+		query["cid"] = cid
+	}
+	if len(name) > 0 {
+		query["name"] = bson.M{"$regex": name, "$options": "$i"}
+	}
+	if len(_uploadTime) > 0 {
+		uploadTime, err := time.Parse("2006-01-02", _uploadTime)
+		if err == nil {
+			startTime := time.Date(uploadTime.Year(), uploadTime.Month(), uploadTime.Day(), 0, 0, 0, 0, uploadTime.Location())
+			endTime := time.Date(uploadTime.Year(), uploadTime.Month(), uploadTime.Day(), 23, 59, 59, 0, uploadTime.Location())
+			query["createTime"] = bson.M{
+				"$gte": startTime,
+				"$lte": endTime,
+			}
+		}
+	}
+
+	result, err := repo.RepoPageSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
+		CollectName: repo.CollectionAr,
+		Page:        page,
+		Size:        size,
+		Query:       query,
+		Sort:        sort,
+	})
+
+	cate := model.Catgory{}
+	if len(result.List) > 0 {
+		for i, u := range result.List {
+			if v, ok := u["cid"]; ok {
+				// 查询角色信息
+				cid := v.(primitive.ObjectID)
+				repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
+					CollectName: repo.CollectionCategories,
+					Query:       repo.Map{"_id": cid},
+				}, &cate)
+			}
+			// 拼接角色信息
+			result.List[i]["cateInfo"] = cate
+		}
+	}
+	return result, err
+}
+
+func UpdateAr(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	Ar := &model.Ar{}
+	err := c.ShouldBindJSON(&Ar)
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+	if Ar.Id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+
+	Ar.UpdateTime = time.Now()
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionAr, Ar.Id.Hex(), Ar)
+}
+
+func ArOn(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	state := 1
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionAr, _id, model.Ar{State: &state})
+}
+
+func ArOff(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	state := -1
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionAr, _id, model.Ar{State: &state})
+}

+ 61 - 0
src/api/cate.go

@@ -0,0 +1,61 @@
+package api
+
+import (
+	"errors"
+	"moutai/log"
+	"time"
+
+	"moutai/db/model"
+	"moutai/db/repo"
+
+	"github.com/gin-gonic/gin"
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+// CategoryCreate 创建分类
+func CategoryCreate(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	var category model.Catgory
+	err := c.ShouldBindJSON(&category)
+	if err != nil {
+		return nil, err
+	}
+	category.CreateTime = time.Now()
+	category.UpdateTime = time.Now()
+	return repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionCategories, &category)
+}
+
+// CategoryDelete 删除分类
+func DeleteCategory(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	return repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionCategories, _id)
+}
+
+// CategoryList 获取分类列表
+func CategoryList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	page, size, query := UtilQueryPageSize(c)
+
+	return repo.RepoPageSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
+		CollectName: repo.CollectionCategories,
+		Page:        page,
+		Size:        size,
+		Query:       query,
+	})
+}
+
+// CategoryUpdate 更新分类
+func UpdateCategory(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	category := &model.Catgory{}
+	err := c.ShouldBindJSON(&category)
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+	if category.Id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionCategories, category.Id.Hex(), category)
+}

+ 32 - 0
src/api/comm.go

@@ -0,0 +1,32 @@
+package api
+
+import (
+	"errors"
+	"moutai/db/repo"
+
+	"github.com/gin-gonic/gin"
+	"go.mongodb.org/mongo-driver/bson"
+)
+
+var clickMap = map[string]struct{}{
+	repo.CollectionImages: {},
+	repo.CollectionVideos: {},
+	repo.CollectionRelics: {},
+	repo.CollectionVr:     {},
+	repo.CollectionAr:     {},
+}
+
+func Clicks(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	ClickType := c.Query("type")
+	id := c.Query("id")
+	if _, ok := clickMap[ClickType]; ok {
+		_, err := repo.RepoUpdateSetDocProps(apictx.CreateRepoCtx(), ClickType, id, bson.M{"$inc": bson.M{"clicks": 1}})
+		if err != nil {
+			return false, err
+		}
+		return true, nil
+
+	}
+	return false, errors.New("参数错误!")
+
+}

+ 0 - 39
src/api/exam.go

@@ -1,39 +0,0 @@
-package api
-
-import (
-	"errors"
-	"fmt"
-	"moutai/db/model"
-	"moutai/db/repo"
-	"time"
-
-	"github.com/gin-gonic/gin"
-)
-
-func ExamHistoryCreate(c *gin.Context, apictx *ApiSession) (interface{}, error) {
-	var form model.ExamHistory
-	err := c.ShouldBindJSON(&form)
-	fmt.Println(form)
-	if err != nil {
-		fmt.Println(err)
-		return nil, errors.New("参数错误")
-	}
-	form.UserId = apictx.User.ID
-	form.CreateTime = time.Now()
-	return repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionExamHistory, &form)
-}
-
-func ExamHistoryList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
-	page, size, query := UtilQueryPageSize(c)
-	// 没有userId时默认自己的
-	if _, ok := query["userId"]; !ok {
-		query["userId"] = apictx.User.ID
-	}
-
-	return repo.RepoPageSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
-		CollectName: repo.CollectionExamHistory,
-		Page:        page,
-		Size:        size,
-		Query:       query,
-	})
-}

+ 53 - 0
src/api/home.go

@@ -0,0 +1,53 @@
+package api
+
+import (
+	"fmt"
+	"moutai/db/model"
+	"moutai/db/repo"
+	"time"
+
+	"github.com/gin-gonic/gin"
+)
+
+func HomeContent(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	var form model.Home
+	err := c.ShouldBindJSON(&form)
+	if err != nil {
+		return nil, err
+	}
+	// 先查询是否存在首页类容
+	home := model.Home{}
+	found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
+		CollectName: repo.CollectionHome,
+	}, &home)
+	if err != nil {
+		return nil, err
+	}
+	form.UpdateTime = time.Now()
+	if found {
+		// 更新
+		return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionHome, home.Id.Hex(), form)
+	} else {
+		// 新增
+		form.CreateTime = time.Now()
+		return repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionRoles, &form)
+	}
+
+}
+
+func HomeDetail(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	var form model.Home
+	err := c.ShouldBindJSON(&form)
+	if err != nil {
+		return nil, err
+	}
+	// 先查询是否存在首页类容
+	home := model.Home{}
+	_, err = repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
+		CollectName: repo.CollectionHome,
+	}, &home)
+	if err != nil {
+		fmt.Println(err)
+	}
+	return home, nil
+}

+ 133 - 0
src/api/image.go

@@ -0,0 +1,133 @@
+package api
+
+import (
+	"errors"
+	"moutai/db/model"
+	"moutai/db/repo"
+	"moutai/log"
+	"strconv"
+	"time"
+
+	"github.com/gin-gonic/gin"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+func CreateImage(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	Image := &model.Images{}
+	err := c.ShouldBindJSON(&Image)
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+
+	// 正常状态
+	state := -1
+	Image.State = &state
+	Image.CreateTime = time.Now()
+	Image.UpdateTime = time.Now()
+	return repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionImages, &Image)
+}
+
+func DeleteImage(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	return repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionImages, _id)
+}
+
+func ImageList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	page, size, query := UtilQueryPageSize(c)
+	_uploadTime := c.Query("uploadTime")
+	_cid := c.Query("cid")
+	cid, _ := primitive.ObjectIDFromHex(_cid)
+	name := c.Query("name")
+	_sort := c.Query("sort")
+	sortInt, _ := strconv.Atoi(_sort)
+	sort := repo.Map{"createTime": -1}
+	if sortInt > 0 {
+		sort = repo.Map{"sort": -1}
+	}
+
+	if !cid.IsZero() {
+		query["cid"] = cid
+	}
+	if len(name) > 0 {
+		query["name"] = bson.M{"$regex": name, "$options": "$i"}
+	}
+	if len(_uploadTime) > 0 {
+		uploadTime, err := time.Parse("2006-01-02", _uploadTime)
+		if err == nil {
+			startTime := time.Date(uploadTime.Year(), uploadTime.Month(), uploadTime.Day(), 0, 0, 0, 0, uploadTime.Location())
+			endTime := time.Date(uploadTime.Year(), uploadTime.Month(), uploadTime.Day(), 23, 59, 59, 0, uploadTime.Location())
+			query["createTime"] = bson.M{
+				"$gte": startTime,
+				"$lte": endTime,
+			}
+		}
+	}
+
+	result, err := repo.RepoPageSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
+		CollectName: repo.CollectionImages,
+		Page:        page,
+		Size:        size,
+		Query:       query,
+		Sort:        sort,
+	})
+
+	cate := model.Catgory{}
+	if len(result.List) > 0 {
+		for i, u := range result.List {
+			if v, ok := u["cid"]; ok {
+				// 查询角色信息
+				cid := v.(primitive.ObjectID)
+				repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
+					CollectName: repo.CollectionCategories,
+					Query:       repo.Map{"_id": cid},
+				}, &cate)
+			}
+			// 拼接角色信息
+			result.List[i]["cateInfo"] = cate
+		}
+	}
+	return result, err
+}
+
+func UpdateImage(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	Image := &model.Images{}
+	err := c.ShouldBindJSON(&Image)
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+	if Image.Id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+
+	Image.UpdateTime = time.Now()
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionImages, Image.Id.Hex(), Image)
+}
+
+func ImageOn(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	state := 1
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionImages, _id, model.Images{State: &state})
+}
+
+func ImageOff(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	state := -1
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionImages, _id, model.Images{State: &state})
+}

+ 132 - 0
src/api/relic.go

@@ -0,0 +1,132 @@
+package api
+
+import (
+	"errors"
+	"moutai/db/model"
+	"moutai/db/repo"
+	"moutai/log"
+	"strconv"
+	"time"
+
+	"github.com/gin-gonic/gin"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+func CreateRelic(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	Relic := &model.Relics{}
+	err := c.ShouldBindJSON(&Relic)
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+	// 正常状态
+	state := -1
+	Relic.State = &state
+	Relic.CreateTime = time.Now()
+	Relic.UpdateTime = time.Now()
+	return repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionRelics, &Relic)
+}
+
+func DeleteRelic(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	return repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionRelics, _id)
+}
+
+func RelicList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	page, size, query := UtilQueryPageSize(c)
+	_uploadTime := c.Query("uploadTime")
+	_cid := c.Query("cid")
+	cid, _ := primitive.ObjectIDFromHex(_cid)
+	name := c.Query("name")
+	_sort := c.Query("sort")
+	sortInt, _ := strconv.Atoi(_sort)
+	sort := repo.Map{"createTime": -1}
+	if sortInt > 0 {
+		sort = repo.Map{"sort": -1}
+	}
+
+	if !cid.IsZero() {
+		query["cid"] = cid
+	}
+	if len(name) > 0 {
+		query["name"] = bson.M{"$regex": name, "$options": "$i"}
+	}
+	if len(_uploadTime) > 0 {
+		uploadTime, err := time.Parse("2006-01-02", _uploadTime)
+		if err == nil {
+			startTime := time.Date(uploadTime.Year(), uploadTime.Month(), uploadTime.Day(), 0, 0, 0, 0, uploadTime.Location())
+			endTime := time.Date(uploadTime.Year(), uploadTime.Month(), uploadTime.Day(), 23, 59, 59, 0, uploadTime.Location())
+			query["createTime"] = bson.M{
+				"$gte": startTime,
+				"$lte": endTime,
+			}
+		}
+	}
+
+	result, err := repo.RepoPageSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
+		CollectName: repo.CollectionRelics,
+		Page:        page,
+		Size:        size,
+		Query:       query,
+		Sort:        sort,
+	})
+
+	cate := model.Catgory{}
+	if len(result.List) > 0 {
+		for i, u := range result.List {
+			if v, ok := u["cid"]; ok {
+				// 查询角色信息
+				cid := v.(primitive.ObjectID)
+				repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
+					CollectName: repo.CollectionCategories,
+					Query:       repo.Map{"_id": cid},
+				}, &cate)
+			}
+			// 拼接角色信息
+			result.List[i]["cateInfo"] = cate
+		}
+	}
+	return result, err
+}
+
+func UpdateRelic(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	Relic := &model.Relics{}
+	err := c.ShouldBindJSON(&Relic)
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+	if Relic.Id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+
+	Relic.UpdateTime = time.Now()
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionRelics, Relic.Id.Hex(), Relic)
+}
+
+func RelicOn(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	state := 1
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionRelics, _id, model.Relics{State: &state})
+}
+
+func RelicOff(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	state := -1
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionRelics, _id, model.Relics{State: &state})
+}

+ 62 - 0
src/api/role.go

@@ -0,0 +1,62 @@
+package api
+
+import (
+	"errors"
+	"moutai/log"
+	"time"
+
+	"moutai/db/model"
+	"moutai/db/repo"
+
+	"github.com/gin-gonic/gin"
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+func RoleCreate(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	var form model.Role
+	err := c.ShouldBindJSON(&form)
+	if err != nil {
+		return nil, err
+	}
+	form.CreateTime = time.Now()
+	form.UpdateTime = time.Now()
+	return repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionRoles, &form)
+}
+
+func DeleteRole(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	return repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionRoles, _id)
+
+}
+
+func RoleList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	page, size, query := UtilQueryPageSize(c)
+
+	return repo.RepoPageSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
+		CollectName: repo.CollectionRoles,
+		Page:        page,
+		Size:        size,
+		Query:       query,
+	})
+
+}
+
+func UpdateRole(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	role := &model.Role{}
+	err := c.ShouldBindJSON(&role)
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+	if role.Id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionUser, role.Id.Hex(), role)
+
+}

+ 75 - 20
src/api/router.go

@@ -9,29 +9,84 @@ import (
 // RegRouters 注册路由
 func RegRouters(svc *Service) {
 
-	crrouter := svc.NewGinRouter("/" + svc.Conf.Name)
-	crrouter.group.Use(Logger())
-	// 用户登录
-	crrouter.POST("/user/login/password", UserLoginPassword)
+	moutai := svc.NewGinRouter("/" + svc.Conf.Name)
+	moutai.group.Use(Logger())
+	// 角色管理
+	moutai.POSTJWT("/admin/role/create", RoleCreate)
+	moutai.POSTJWT("/admin/role/delete/:id", DeleteRole)
+	moutai.GETJWT("/admin/role/list", RoleList)
+	moutai.POSTJWT("/admin/role/update", UpdateRole)
+
 	// 用户管理
-	crrouter.POSTJWT("/admin/user/create", CreateUser)
-	crrouter.POSTJWT("/admin/user/delete/:id", DeleteUser)
-	crrouter.POSTJWT("/admin/user/delete/batch", BatchDeleteUser)
-	crrouter.GETJWT("/admin/user/list", UserList)
-	// crrouter.GETJWT("/admin/user/detail/:id", UserDetail)
-	crrouter.POSTJWT("/admin/user/update", UpdateUser)
+	moutai.POST("/user/login/password", UserLoginPassword)
+	moutai.POSTJWT("/admin/user/create", CreateUser)
+	moutai.POSTJWT("/admin/user/delete/:id", DeleteUser)
+	moutai.GETJWT("/admin/user/list", UserList)
+	moutai.POSTJWT("/admin/user/update", UpdateUser)
+	moutai.POSTJWT("/admin/user/disable/:id", DisableUser)
+	moutai.POSTJWT("/admin/user/enable/:id", EnableUser)
+	// 获取自己的详情信息
+	moutai.GETJWT("/user/profile", UserProfile)
 
-	crrouter.POSTJWT("/admin/user/import", ImportUser)
-	crrouter.GETJWT("/admin/user/export", ExportUser)
-	crrouter.GETJWT("/admin/user/tmplate", UserTmplate)
+	// 分类管理
+	moutai.POSTJWT("/admin/cate/create", CategoryCreate)
+	moutai.POSTJWT("/admin/cate/delete/:id", DeleteCategory)
+	moutai.GETJWT("/admin/cate/list", CategoryList)
+	moutai.POSTJWT("/admin/cate/update", UpdateCategory)
 
-	// 获取自己的详情信息
-	crrouter.GETJWT("/user/profile", UserProfile)
-	// 增加用户学习时长
-	// crrouter.GETJWT("/user/learn/inc", UserLearnInc)
-	// 考核历史
-	crrouter.POSTJWT("/exam/history/create", ExamHistoryCreate)
-	crrouter.GETJWT("/exam/history/list", ExamHistoryList)
+	// 首页内容
+	moutai.POSTJWT("/admin/home/content", HomeContent)
+	moutai.GET("/admin/home/content", HomeDetail)
+
+	// 图片管理
+	moutai.POSTJWT("/admin/image/create", CreateImage)
+	moutai.POSTJWT("/admin/image/delete/:id", DeleteImage)
+	moutai.GET("/image/list", ImageList)
+	moutai.POSTJWT("/admin/image/update", UpdateImage)
+	// 上架
+	moutai.POSTJWT("/admin/image/on/:id", ImageOn)
+	// 下架
+	moutai.POSTJWT("/admin/image/off/:id", ImageOff)
+
+	// 视频管理
+	moutai.POSTJWT("/admin/video/create", CreateVideo)
+	moutai.POSTJWT("/admin/video/delete/:id", DeleteVideo)
+	moutai.GET("/video/list", VideoList)
+	moutai.POSTJWT("/admin/video/update", UpdateVideo)
+	// 上架
+	moutai.POSTJWT("/admin/video/on/:id", VideoOn)
+	// 下架
+	moutai.POSTJWT("/admin/video/off/:id", VideoOff)
+
+	// 3d文物管理 relics
+	moutai.POSTJWT("/admin/relic/create", CreateRelic)
+	moutai.POSTJWT("/admin/relic/delete/:id", DeleteRelic)
+	moutai.GET("/relic/list", RelicList)
+	moutai.POSTJWT("/admin/relic/update", UpdateRelic)
+	// 上架
+	moutai.POSTJWT("/admin/relic/on/:id", RelicOn)
+	// 下架
+	moutai.POSTJWT("/admin/relic/off/:id", RelicOff)
+
+	// vr管理
+	moutai.POSTJWT("/admin/vr/create", CreateVr)
+	moutai.POSTJWT("/admin/vr/delete/:id", DeleteVr)
+	moutai.GET("/vr/list", VrList)
+	moutai.POSTJWT("/admin/vr/update", UpdateVr)
+	// 上架
+	moutai.POSTJWT("/admin/vr/on/:id", VrOn)
+	// 下架
+	moutai.POSTJWT("/admin/vr/off/:id", VrOff)
+
+	// ar管理
+	moutai.POSTJWT("/admin/ar/create", CreateAr)
+	moutai.POSTJWT("/admin/ar/delete/:id", DeleteAr)
+	moutai.GET("/ar/list", ArList)
+	moutai.POSTJWT("/admin/ar/update", UpdateAr)
+	// 上架
+	moutai.POSTJWT("/admin/ar/on/:id", ArOn)
+	// 下架
+	moutai.POSTJWT("/admin/ar/off/:id", ArOff)
 
 }
 

+ 0 - 197
src/api/user-excel.go

@@ -1,197 +0,0 @@
-package api
-
-import (
-	"fmt"
-	"moutai/db/model"
-	"strings"
-
-	"github.com/xuri/excelize/v2"
-)
-
-type UserExcel struct {
-	Offset           int
-	Row              int
-	Title            string //标题
-	Excel            *excelize.File
-	SheetName        string
-	AlignCenterStyle int
-	Content          []*model.User
-	RowMap           map[string]int
-	RowWidthArray    []float64
-	RowsHeightArray  []map[int]float64
-}
-
-// 批量设置行高
-func (b *UserExcel) setRowsHeight() {
-	for _, rowHeight := range b.RowsHeightArray {
-		for row, height := range rowHeight {
-			b.Excel.SetRowHeight(b.SheetName, row, height)
-		}
-	}
-
-}
-
-// 获取范围内单元格的宽度 A:F
-func (b *UserExcel) getRangeWidth(r string) float64 {
-	rg := strings.Split(r, ":")
-
-	if len(rg) == 1 {
-		start := b.RowMap[rg[0]]
-		return b.RowWidthArray[start]
-	} else if len(rg) == 2 {
-		start := b.RowMap[rg[0]]
-		end := b.RowMap[rg[1]]
-		rowr := b.RowWidthArray[start : end+1]
-		width := 0.0
-		for _, v := range rowr {
-			width += v
-		}
-		return width
-	}
-	return 0.0
-}
-
-func (b *UserExcel) drawTitle() error {
-	b.Row++
-	startCell := fmt.Sprintf("A%d", b.Row)
-	endCell := fmt.Sprintf("D%d", b.Row)
-
-	b.RowMap = map[string]int{"A": 0, "B": 1, "C": 2, "D": 3}
-
-	b.RowWidthArray = []float64{12, 12, 12, 36}
-	b.Excel.SetColWidth(b.SheetName, "A", "A", 12)
-	b.Excel.SetColWidth(b.SheetName, "B", "B", 12)
-	b.Excel.SetColWidth(b.SheetName, "C", "C", 12)
-	b.Excel.SetColWidth(b.SheetName, "D", "D", 36)
-
-	err := b.Excel.MergeCell(b.SheetName, startCell, endCell)
-	if err != nil {
-		return err
-	}
-
-	style, err := b.Excel.NewStyle(&excelize.Style{
-		Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"},
-		Font:      &excelize.Font{Bold: true, Size: 18}})
-	if err != nil {
-		return err
-	}
-	err = b.Excel.SetCellStyle(b.SheetName, startCell, startCell, style)
-	if err != nil {
-		return err
-	}
-	b.Excel.SetRowHeight(b.SheetName, b.Row, 26)
-
-	b.Excel.SetCellValue(b.SheetName, startCell, b.Title)
-	return nil
-}
-
-func (b *UserExcel) drawTableTitle() error {
-	b.Row++
-	var drawCol = func(prefix string, value string) error {
-		cell := fmt.Sprintf("%s%d", prefix, b.Row)
-		err := b.Excel.SetCellStyle(b.SheetName, cell, cell, b.AlignCenterStyle)
-		if err != nil {
-			return err
-		}
-
-		return b.Excel.SetCellValue(b.SheetName, cell, value)
-	}
-
-	drawCol("A", "账号")
-	drawCol("B", "昵称")
-	drawCol("C", "角色")
-	drawCol("D", "密码")
-	b.Excel.SetRowHeight(b.SheetName, b.Row, 22)
-
-	return nil
-}
-
-func (b *UserExcel) drawTableContent() error {
-	b.Row++
-	var DrawRow = func(rowIndex int, values ...string) float64 {
-		charas := []string{"A", "B", "C", "D"}
-		// 获取该行最大行高
-		max := getRowHeight(values[0], b.getRangeWidth(charas[0]))
-		for i, c := range charas {
-			v := ""
-			if i < len(values) {
-				v = values[i]
-			}
-			b.Excel.SetCellValue(b.SheetName, fmt.Sprintf("%s%d", c, rowIndex), v)
-			val2Cel := fmt.Sprintf("%s%d", c, rowIndex)
-			b.Excel.SetCellStyle(b.SheetName, val2Cel, val2Cel, b.AlignCenterStyle)
-
-			if getRowHeight(v, b.getRangeWidth(c)) > max {
-				max = getRowHeight(v, b.getRangeWidth(c))
-			}
-		}
-		return max
-	}
-
-	users := b.Content
-	if len(users) > 0 {
-		for _, user := range users {
-			role := ""
-			if user.Roles[0] == "admin" {
-				role = "管理员"
-			}
-			if user.Roles[0] == "teacher" {
-				role = "教员"
-			}
-			if user.Roles[0] == "student" {
-				role = "学员"
-			}
-			rowMaxHeight := DrawRow(b.Row, user.LoginName, user.Nid, role, user.Password)
-			b.RowsHeightArray = append(b.RowsHeightArray, map[int]float64{b.Row: rowMaxHeight})
-			b.Row++
-		}
-	}
-
-	return nil
-}
-
-func (b *UserExcel) Draws() {
-	b.drawTitle()
-
-	b.drawTableTitle()
-	b.drawTableContent()
-	// 设置行高
-	b.setRowsHeight()
-}
-
-func NewUserExcel(f *excelize.File) *UserExcel {
-
-	border := []excelize.Border{
-		{Type: "top", Style: 1, Color: "000000"},
-		{Type: "left", Style: 1, Color: "000000"},
-		{Type: "right", Style: 1, Color: "000000"},
-		{Type: "bottom", Style: 1, Color: "000000"},
-	}
-
-	styleLeft, _ := f.NewStyle(&excelize.Style{
-		Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true},
-		Border:    border,
-	})
-
-	b := &UserExcel{
-		Title:            "用户信息",
-		SheetName:        "Sheet1",
-		Excel:            f,
-		Offset:           0,
-		AlignCenterStyle: styleLeft,
-		RowMap:           map[string]int{"A": 0, "B": 1, "C": 2, "D": 3},
-		RowWidthArray:    []float64{12, 12, 12, 20},
-		RowsHeightArray:  make([]map[int]float64, 0),
-	}
-
-	// f.SetPageMargins(b.SheetName, excelize.PageMarginTop(1), excelize.PageMarginLeft(0), excelize.PageMarginRight(0))
-
-	return b
-}
-
-func (b *UserExcel) FormatToEmpty(str *string) {
-	if *str == "0" || *str == "0.000" {
-		*str = "-"
-	}
-
-}

+ 61 - 311
src/api/user.go

@@ -2,9 +2,7 @@ package api
 
 import (
 	"errors"
-	"fmt"
 	"moutai/log"
-	"net/url"
 	"time"
 
 	"moutai/db/model"
@@ -12,39 +10,34 @@ import (
 	"moutai/utils"
 
 	"github.com/gin-gonic/gin"
-	"github.com/xuri/excelize/v2"
 	"go.mongodb.org/mongo-driver/bson"
 	"go.mongodb.org/mongo-driver/bson/primitive"
 )
 
-type UserLoginPasswordReq struct {
-	LoginName string `json:"loginName"`
-	Password  string `json:"password"`
-	Role      string `json:"role"`
-}
-
 func UserLoginPassword(c *gin.Context, apictx *ApiSession) (interface{}, error) {
-	var form UserLoginPasswordReq
+	var form model.User
 	err := c.ShouldBindJSON(&form)
 	if err != nil {
 		return nil, err
 	}
 
-	// 查找用户:根据longinName/password/role是否在roles中
+	// 正常用户登录
 	user := &model.User{}
 	found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
 		CollectName: repo.CollectionUser,
 		Query: repo.Map{
 			"loginName": form.LoginName,
 			"password":  utils.UtilMd5(form.Password),
-			"roles":     bson.M{"$elemMatch": bson.M{"$eq": form.Role}},
 		},
 	}, user)
 	if err != nil {
 		return nil, err
 	}
 	if !found {
-		return nil, errors.New("账号/密码/角色不正确")
+		return nil, errors.New("账号/密码不正确!")
+	}
+	if *user.State == -1 {
+		return nil, errors.New("该账号已被禁用!")
 	}
 
 	jwtU := &JWTUser{ID: user.GetID()}
@@ -63,19 +56,11 @@ func UserLoginPassword(c *gin.Context, apictx *ApiSession) (interface{}, error)
 }
 
 // 用户唯一
-// db.users.createIndex({ nid: 1 }, { unique: true })
+// db.users.createIndex({ loginName: 1 }, { unique: true })
 func CreateUser(c *gin.Context, apictx *ApiSession) (interface{}, error) {
-	// 验证是否为管理员
-	isAdmin, err := IsAdmin(c, apictx)
-	if err != nil {
-		return nil, err
-	}
-	if !isAdmin {
-		return nil, errors.New("没有权限")
-	}
 
 	user := &model.User{}
-	err = c.ShouldBindJSON(&user)
+	err := c.ShouldBindJSON(&user)
 	if err != nil {
 		log.Error(err)
 		return nil, err
@@ -93,10 +78,9 @@ func CreateUser(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 		return nil, errors.New("该账号已存在")
 	}
 
-	// student,teacher,admin
-	if len(user.Roles) < 1 {
-		user.Roles = []string{"student"}
-	}
+	// 正常状态
+	state := 1
+	user.State = &state
 	user.Password = UtilMd5(user.Password)
 	user.CreateTime = time.Now()
 	user.UpdateTime = time.Now()
@@ -104,14 +88,6 @@ func CreateUser(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 }
 
 func DeleteUser(c *gin.Context, apictx *ApiSession) (interface{}, error) {
-	// 验证是否为管理员
-	isAdmin, err := IsAdmin(c, apictx)
-	if err != nil {
-		return nil, err
-	}
-	if !isAdmin {
-		return nil, errors.New("没有权限")
-	}
 	_id := c.Param("id")
 	id, _ := primitive.ObjectIDFromHex(_id)
 	if id.IsZero() {
@@ -120,93 +96,52 @@ func DeleteUser(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 	return repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionUser, _id)
 }
 
-type BatchDeleteUserReq struct {
-	Ids []string `json:"ids"`
-}
-
-func BatchDeleteUser(c *gin.Context, apictx *ApiSession) (interface{}, error) {
-	// 验证是否为管理员
-	isAdmin, err := IsAdmin(c, apictx)
-	if err != nil {
-		return nil, err
-	}
-	if !isAdmin {
-		return nil, errors.New("没有权限")
-	}
-	var form BatchDeleteUserReq
-	err = c.ShouldBindJSON(&form)
-	if err != nil {
-		return nil, errors.New("参数错误")
-	}
-	if len(form.Ids) > 0 {
-		for _, id := range form.Ids {
-			repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionUser, id)
-		}
-	}
-	return true, nil
-}
-
 // 用户列表
-// /user/list?role=student&name=xxx&nid=xxx&page=1&size=10
+// /user/list?roleId=xxx&name=xxx
 func UserList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
-	// 验证是否为管理员
-	isStudent, err := IsStudent(c, apictx)
-	if err != nil {
-		return nil, err
-	}
-	if isStudent {
-		return nil, errors.New("没有权限")
-	}
 	page, size, query := UtilQueryPageSize(c)
-	role := c.Query("role")
+	_roleId := c.Query("roleId")
+	roleId, _ := primitive.ObjectIDFromHex(_roleId)
 	name := c.Query("name")
 
-	if len(role) > 0 {
-		query["roles"] = bson.M{"$elemMatch": bson.M{"$eq": role}}
+	if !roleId.IsZero() {
+		query["roleId"] = roleId
 	}
 	if len(name) > 0 {
 		query["name"] = bson.M{"$regex": name, "$options": "$i"}
 	}
 
-	return repo.RepoPageSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
+	result, err := repo.RepoPageSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
 		CollectName: repo.CollectionUser,
 		Page:        page,
 		Size:        size,
 		Query:       query,
 		Sort:        bson.D{bson.E{Key: "createTime", Value: -1}, bson.E{Key: "_id", Value: -1}},
-		Project:     []string{"name", "loginName", "avatar", "roles", "createTime", "updateTime"},
+		Project:     []string{"roleId", "name", "loginName", "avatar", "state", "createTime", "updateTime"},
 	})
 
-}
-
-func UserDetail(c *gin.Context, apictx *ApiSession) (interface{}, error) {
-	// 验证是否为管理员
-	isAdmin, err := IsAdmin(c, apictx)
-	if err != nil {
-		return nil, err
-	}
-	if !isAdmin {
-		return nil, errors.New("没有权限")
-	}
-	_id := c.Param("id")
-	id, _ := primitive.ObjectIDFromHex(_id)
-	if id.IsZero() {
-		return nil, errors.New("id错误")
+	role := model.Role{}
+	if len(result.List) > 0 {
+		for i, u := range result.List {
+			if v, ok := u["roleId"]; ok {
+				// 查询角色信息
+				roleId := v.(primitive.ObjectID)
+				repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
+					CollectName: repo.CollectionRoles,
+					Query:       repo.Map{"_id": roleId},
+				}, &role)
+			}
+			// 拼接角色信息
+			result.List[i]["roleInfo"] = role
+		}
 	}
-	return GetUserById(apictx, _id)
+	return result, err
 }
 
 func UpdateUser(c *gin.Context, apictx *ApiSession) (interface{}, error) {
-	// 验证是否为管理员
-	isAdmin, err := IsAdmin(c, apictx)
-	if err != nil {
-		return nil, err
-	}
-	if !isAdmin {
-		return nil, errors.New("没有权限")
-	}
+
 	user := &model.User{}
-	err = c.ShouldBindJSON(&user)
+	err := c.ShouldBindJSON(&user)
 	if err != nil {
 		log.Error(err)
 		return nil, err
@@ -218,11 +153,27 @@ func UpdateUser(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 	if len(user.Password) > 0 {
 		user.Password = UtilMd5(user.Password)
 	}
-	result, err := repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionUser, user.Id.Hex(), user)
-	if err != nil {
-		return nil, errors.New("更新失败,请检查编码是否重复")
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionUser, user.Id.Hex(), user)
+}
+
+func DisableUser(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
 	}
-	return result, err
+	state := -1
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionUser, _id, model.User{State: &state})
+}
+
+func EnableUser(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	state := 1
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionUser, _id, model.User{State: &state})
 }
 
 // 获取自己的信息
@@ -230,29 +181,6 @@ func UserProfile(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 	return GetUserById(apictx, apictx.User.ID)
 }
 
-// func UserLearnInc(c *gin.Context, apictx *ApiSession) (interface{}, error) {
-// 	_time := c.Query("t")
-// 	increase, _ := strconv.Atoi(_time)
-// 	if increase < 1 {
-
-// 		return false, fmt.Errorf("增加学习时长小于1: %d", increase)
-// 	}
-// 	userInfo, err := GetUserById(apictx, apictx.User.ID)
-// 	if err != nil {
-// 		return false, errors.New("未找到该用户信息")
-// 	}
-// 	learnTime := userInfo.LearnTime
-// 	// 增加学习时长
-// 	newTime := learnTime + increase
-// 	_, err = repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionUser, apictx.User.ID, &model.User{LearnTime: newTime})
-// 	if err != nil {
-// 		fmt.Println(err)
-// 		log.Error(err)
-// 		return false, errors.New("更新学习时长出错")
-// 	}
-// 	return true, nil
-// }
-
 // 根据id获取用户信息
 func GetUserById(apictx *ApiSession, id string) (*model.User, error) {
 	user := &model.User{}
@@ -268,190 +196,12 @@ func GetUserById(apictx *ApiSession, id string) (*model.User, error) {
 	if !found {
 		return nil, errors.New("未找到该数据")
 	}
+	role := model.Role{}
+	repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
+		CollectName: repo.CollectionRoles,
+		Query:       repo.Map{"_id": user.RoleId},
+	}, &role)
+	user.RoleInfo = &role
 	user.Password = ""
 	return user, nil
 }
-
-// 是否是管理员
-func IsAdmin(c *gin.Context, apictx *ApiSession) (bool, error) {
-	user, err := GetUserById(apictx, apictx.User.ID)
-	if err != nil {
-		return false, err
-	}
-	for _, v := range user.Roles {
-		if v == "admin" {
-			return true, nil
-		}
-	}
-	return false, nil
-}
-
-// 是否是老师
-func IsTeacher(c *gin.Context, apictx *ApiSession) (bool, error) {
-	user, err := GetUserById(apictx, apictx.User.ID)
-	if err != nil {
-		return false, err
-	}
-	for _, v := range user.Roles {
-		if v == "teacher" {
-			return true, nil
-		}
-	}
-	return false, nil
-}
-
-// 是否是学生
-func IsStudent(c *gin.Context, apictx *ApiSession) (bool, error) {
-	user, err := GetUserById(apictx, apictx.User.ID)
-	if err != nil {
-		return false, err
-	}
-	for _, v := range user.Roles {
-		if v == "student" {
-			return true, nil
-		}
-	}
-	return false, nil
-}
-
-// 导入用户
-func ImportUser(c *gin.Context, apictx *ApiSession) (interface{}, error) {
-	isAdmin, err := IsAdmin(c, apictx)
-	if err != nil {
-		return nil, err
-	}
-	if !isAdmin {
-		return nil, errors.New("没有权限")
-	}
-	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
-	}
-	errors := []string{}
-
-	if len(users) > 0 {
-		for index, us := range users {
-			rowNum := index + 1
-			// 标题行
-			if index == 0 {
-				continue
-			}
-			// 表头
-			if index == 1 {
-				continue
-			}
-			// 去除可能的空行
-			if len(us) == 0 {
-				continue
-			}
-			// 用户名name 编号nid 密码password 角色roles
-			user := &model.User{}
-			user.LoginName = us[0]
-			user.Nid = us[1]
-			if len(us[0]) == 0 {
-				errors = append(errors, fmt.Sprintf("第%d行错误: %s", rowNum, "账号不能为空"))
-				continue
-			}
-			// !查询用户,确保账号名唯一,用数据库唯一索引约束:db.users.createIndex({ loginName: 1 }, { unique: true })
-
-			roles := []string{}
-			if us[2] == "管理员" {
-				roles = []string{"admin"}
-			}
-			if us[2] == "教员" {
-				roles = []string{"teacher"}
-			}
-			if us[2] == "学员" {
-				roles = []string{"student"}
-			}
-			user.Roles = roles
-			user.Password = UtilMd5(us[3])
-			if len(us[3]) == 0 {
-				user.Password = UtilMd5("123456")
-			} else if len(us[3]) == 32 {
-				user.Password = us[3]
-			}
-
-			user.CreateTime = time.Now()
-			user.UpdateTime = time.Now()
-
-			_, err = repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionUser, user)
-			if err != nil {
-				errors = append(errors, fmt.Sprintf("第%d行错误: %s", rowNum, "保存数据失败, 请检查数据格式是否正确/账号是否重复"))
-				log.Error(err)
-			}
-
-		}
-	}
-
-	return errors, nil
-}
-
-// 导出用户
-func ExportUser(c *gin.Context, apictx *ApiSession) (interface{}, error) {
-	isAdmin, err := IsAdmin(c, apictx)
-	if err != nil {
-		return nil, err
-	}
-	if !isAdmin {
-		return nil, errors.New("没有权限")
-	}
-	f := excelize.NewFile()
-	index, _ := f.NewSheet("Sheet1")
-	f.SetActiveSheet(index)
-	f.SetDefaultFont("宋体")
-
-	testExcel := NewUserExcel(f)
-	testExcel.Title = "用户信息"
-
-	_, _, query := UtilQueryPageSize(c)
-	// 获取试题列表
-	users := make([]*model.User, 0)
-	err = repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
-		CollectName: repo.CollectionUser,
-		Query:       query,
-		Sort:        bson.M{"createTime": 1},
-	}, &users)
-	if err != nil {
-		return nil, err
-	}
-	testExcel.Content = users
-	testExcel.Draws()
-	fileName := url.PathEscape("用户信息.xlsx")
-	c.Header("Content-Type", "application/octet-stream")
-	c.Header("Content-Disposition", "attachment; filename="+fileName)
-	c.Header("Content-Transfer-Encoding", "binary")
-
-	err = f.Write(c.Writer)
-	if err != nil {
-		return nil, err
-	}
-
-	return nil, nil
-}
-
-// 下载用户模板
-func UserTmplate(c *gin.Context, apictx *ApiSession) (interface{}, error) {
-	filename := "用户信息模板.xlsx"
-	// url.PathEscape将字符串中的特殊字符进行编码,使其符合URL规范
-	filename = url.PathEscape(filename)
-
-	// 设置下载的文件名
-	c.Writer.Header().Add("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
-
-	// 设置文件类型
-	c.Writer.Header().Add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
-
-	c.File("./template/用户信息模板.xlsx")
-	return nil, nil
-}

+ 0 - 19
src/api/utils.go

@@ -1,19 +0,0 @@
-package api
-
-import "math"
-
-// func getRowHeight(content string, width float64,lineHeight float64) float64 {
-// 第一个参数为 行宽 第二个参数为 行高
-func getRowHeight(content string, params ...float64) float64 {
-	var perHeight float64 = 16
-	if len(params) == 2 {
-		perHeight = params[1]
-	}
-	num := float64(len([]rune(content)))
-	// 一行能容纳多少字
-	rowNum := params[0] / 1.5
-	// 向上取整获取行数 * 每行高度
-	rowHeight := math.Ceil(num/rowNum) * perHeight
-	return rowHeight
-
-}

+ 133 - 0
src/api/video.go

@@ -0,0 +1,133 @@
+package api
+
+import (
+	"errors"
+	"moutai/db/model"
+	"moutai/db/repo"
+	"moutai/log"
+	"strconv"
+	"time"
+
+	"github.com/gin-gonic/gin"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+func CreateVideo(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	Video := &model.Videos{}
+	err := c.ShouldBindJSON(&Video)
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+
+	// 正常状态
+	state := -1
+	Video.State = &state
+	Video.CreateTime = time.Now()
+	Video.UpdateTime = time.Now()
+	return repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionVideos, &Video)
+}
+
+func DeleteVideo(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	return repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionVideos, _id)
+}
+
+func VideoList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	page, size, query := UtilQueryPageSize(c)
+	_uploadTime := c.Query("uploadTime")
+	_cid := c.Query("cid")
+	cid, _ := primitive.ObjectIDFromHex(_cid)
+	name := c.Query("name")
+	_sort := c.Query("sort")
+	sortInt, _ := strconv.Atoi(_sort)
+	sort := repo.Map{"createTime": -1}
+	if sortInt > 0 {
+		sort = repo.Map{"sort": -1}
+	}
+
+	if !cid.IsZero() {
+		query["cid"] = cid
+	}
+	if len(name) > 0 {
+		query["name"] = bson.M{"$regex": name, "$options": "$i"}
+	}
+	if len(_uploadTime) > 0 {
+		uploadTime, err := time.Parse("2006-01-02", _uploadTime)
+		if err == nil {
+			startTime := time.Date(uploadTime.Year(), uploadTime.Month(), uploadTime.Day(), 0, 0, 0, 0, uploadTime.Location())
+			endTime := time.Date(uploadTime.Year(), uploadTime.Month(), uploadTime.Day(), 23, 59, 59, 0, uploadTime.Location())
+			query["createTime"] = bson.M{
+				"$gte": startTime,
+				"$lte": endTime,
+			}
+		}
+	}
+
+	result, err := repo.RepoPageSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
+		CollectName: repo.CollectionVideos,
+		Page:        page,
+		Size:        size,
+		Query:       query,
+		Sort:        sort,
+	})
+
+	cate := model.Catgory{}
+	if len(result.List) > 0 {
+		for i, u := range result.List {
+			if v, ok := u["cid"]; ok {
+				// 查询角色信息
+				cid := v.(primitive.ObjectID)
+				repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
+					CollectName: repo.CollectionCategories,
+					Query:       repo.Map{"_id": cid},
+				}, &cate)
+			}
+			// 拼接角色信息
+			result.List[i]["cateInfo"] = cate
+		}
+	}
+	return result, err
+}
+
+func UpdateVideo(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	Video := &model.Videos{}
+	err := c.ShouldBindJSON(&Video)
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+	if Video.Id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+
+	Video.UpdateTime = time.Now()
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionVideos, Video.Id.Hex(), Video)
+}
+
+func VideoOn(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	state := 1
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionVideos, _id, model.Videos{State: &state})
+}
+
+func VideoOff(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	state := -1
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionVideos, _id, model.Videos{State: &state})
+}

+ 133 - 0
src/api/vr.go

@@ -0,0 +1,133 @@
+package api
+
+import (
+	"errors"
+	"moutai/db/model"
+	"moutai/db/repo"
+	"moutai/log"
+	"strconv"
+	"time"
+
+	"github.com/gin-gonic/gin"
+	"go.mongodb.org/mongo-driver/bson"
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+func CreateVr(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	Vr := &model.Vr{}
+	err := c.ShouldBindJSON(&Vr)
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+
+	// 正常状态
+	state := -1
+	Vr.State = &state
+	Vr.CreateTime = time.Now()
+	Vr.UpdateTime = time.Now()
+	return repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionVr, &Vr)
+}
+
+func DeleteVr(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	return repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionVr, _id)
+}
+
+func VrList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	page, size, query := UtilQueryPageSize(c)
+	_uploadTime := c.Query("uploadTime")
+	_cid := c.Query("cid")
+	cid, _ := primitive.ObjectIDFromHex(_cid)
+	name := c.Query("name")
+	_sort := c.Query("sort")
+	sortInt, _ := strconv.Atoi(_sort)
+	sort := repo.Map{"createTime": -1}
+	if sortInt > 0 {
+		sort = repo.Map{"sort": -1}
+	}
+
+	if !cid.IsZero() {
+		query["cid"] = cid
+	}
+	if len(name) > 0 {
+		query["name"] = bson.M{"$regex": name, "$options": "$i"}
+	}
+	if len(_uploadTime) > 0 {
+		uploadTime, err := time.Parse("2006-01-02", _uploadTime)
+		if err == nil {
+			startTime := time.Date(uploadTime.Year(), uploadTime.Month(), uploadTime.Day(), 0, 0, 0, 0, uploadTime.Location())
+			endTime := time.Date(uploadTime.Year(), uploadTime.Month(), uploadTime.Day(), 23, 59, 59, 0, uploadTime.Location())
+			query["createTime"] = bson.M{
+				"$gte": startTime,
+				"$lte": endTime,
+			}
+		}
+	}
+
+	result, err := repo.RepoPageSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
+		CollectName: repo.CollectionVr,
+		Page:        page,
+		Size:        size,
+		Query:       query,
+		Sort:        sort,
+	})
+
+	cate := model.Catgory{}
+	if len(result.List) > 0 {
+		for i, u := range result.List {
+			if v, ok := u["cid"]; ok {
+				// 查询角色信息
+				cid := v.(primitive.ObjectID)
+				repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
+					CollectName: repo.CollectionCategories,
+					Query:       repo.Map{"_id": cid},
+				}, &cate)
+			}
+			// 拼接角色信息
+			result.List[i]["cateInfo"] = cate
+		}
+	}
+	return result, err
+}
+
+func UpdateVr(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	Vr := &model.Vr{}
+	err := c.ShouldBindJSON(&Vr)
+	if err != nil {
+		log.Error(err)
+		return nil, err
+	}
+	if Vr.Id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+
+	Vr.UpdateTime = time.Now()
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionVr, Vr.Id.Hex(), Vr)
+}
+
+func VrOn(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	state := 1
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionVr, _id, model.Vr{State: &state})
+}
+
+func VrOff(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	_id := c.Param("id")
+	id, _ := primitive.ObjectIDFromHex(_id)
+	if id.IsZero() {
+		return nil, errors.New("id错误")
+	}
+	state := -1
+	return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionVr, _id, model.Vr{State: &state})
+}

+ 24 - 0
src/db/model/ar.go

@@ -0,0 +1,24 @@
+package model
+
+import (
+	"time"
+
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+type Ar struct {
+	Id       primitive.ObjectID `bson:"_id,omitempty" json:"_id,omitempty"`
+	Cid      primitive.ObjectID `bson:"cid,omitempty" json:"cid,omitempty"`
+	Cover    string             `bson:"cover,omitempty" json:"cover,omitempty"`
+	Name     string             `bson:"name,omitempty" json:"name,omitempty"`
+	Qr       string             `bson:"qr,omitempty" json:"qr,omitempty"`
+	AdminUrl string             `bson:"adminUrl,omitempty" json:"adminUrl,omitempty"`
+
+	Clicks int `bson:"clicks,omitempty" json:"clicks,omitempty"`
+	Sort   int `bson:"sort,omitempty" json:"sort,omitempty"`
+
+	CreateTime time.Time `bson:"createTime,omitempty" json:"createTime,omitempty"`
+	UpdateTime time.Time `bson:"updateTime,omitempty" json:"updateTime,omitempty"`
+	// 1 上架 -1下架
+	State *int `bson:"state,omitempty" json:"state,omitempty"`
+}

+ 17 - 0
src/db/model/cate.go

@@ -0,0 +1,17 @@
+package model
+
+import (
+	"time"
+
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+type Catgory struct {
+	Id   primitive.ObjectID `bson:"_id,omitempty" json:"_id,omitempty"`
+	Name string             `bson:"name,omitempty" json:"name,omitempty"`
+	// 分类类型: 图片/视频/vr...
+	Type string `bson:"type,omitempty" json:"type,omitempty"`
+
+	CreateTime time.Time `bson:"createTime,omitempty" json:"createTime,omitempty"`
+	UpdateTime time.Time `bson:"updateTime,omitempty" json:"updateTime,omitempty"`
+}

+ 0 - 25
src/db/model/examHistory.go

@@ -1,25 +0,0 @@
-package model
-
-import (
-	"time"
-
-	"go.mongodb.org/mongo-driver/bson/primitive"
-)
-
-type ExamHistory struct {
-	Id          primitive.ObjectID `bson:"_id,omitempty" json:"_id"`
-	UserId      string             `bson:"userId,omitempty" json:"userId"`
-	ProduceName string             `bson:"produceName,omitempty" json:"produceName"`
-	// $title:正确/错误
-	ExamRecord []*Record `bson:"examRecord,omitempty" json:"examRecord"`
-	TotalScore int       `bson:"totalScore,omitempty" json:"totalScore"`
-	Correct    int       `bson:"correct,omitempty" json:"correct"`
-	Mistake    int       `bson:"mistake,omitempty" json:"mistake"`
-	CreateTime time.Time `bson:"createTime,omitempty" json:"createTime"`
-}
-
-type Record struct {
-	Title     string `bson:"title,omitempty" json:"title"`
-	Result    string `bson:"result,omitempty" json:"result"`
-	IsCorrect *bool  `bson:"isCorrect,omitempty" json:"isCorrect"`
-}

+ 15 - 0
src/db/model/home.go

@@ -0,0 +1,15 @@
+package model
+
+import (
+	"time"
+
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+type Home struct {
+	Id      primitive.ObjectID `bson:"_id,omitempty" json:"_id,omitempty"`
+	Content string             `bson:"content,omitempty" json:"content,omitempty"`
+
+	CreateTime time.Time `bson:"createTime,omitempty" json:"createTime,omitempty"`
+	UpdateTime time.Time `bson:"updateTime,omitempty" json:"updateTime,omitempty"`
+}

+ 22 - 0
src/db/model/image.go

@@ -0,0 +1,22 @@
+package model
+
+import (
+	"time"
+
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+type Images struct {
+	Id     primitive.ObjectID `bson:"_id,omitempty" json:"_id,omitempty"`
+	Cid    primitive.ObjectID `bson:"cid,omitempty" json:"cid,omitempty"`
+	Url    string             `bson:"url,omitempty" json:"url,omitempty"`
+	Name   string             `bson:"name,omitempty" json:"name,omitempty"`
+	Desc   string             `bson:"desc,omitempty" json:"desc,omitempty"`
+	Clicks int                `bson:"clicks,omitempty" json:"clicks,omitempty"`
+	Sort   int                `bson:"sort,omitempty" json:"sort,omitempty"`
+
+	CreateTime time.Time `bson:"createTime,omitempty" json:"createTime,omitempty"`
+	UpdateTime time.Time `bson:"updateTime,omitempty" json:"updateTime,omitempty"`
+	// 1 上架 -1下架
+	State *int `bson:"state,omitempty" json:"state,omitempty"`
+}

+ 36 - 0
src/db/model/relic.go

@@ -0,0 +1,36 @@
+package model
+
+import (
+	"time"
+
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+type Relics struct {
+	Id       primitive.ObjectID `bson:"_id,omitempty" json:"_id,omitempty"`
+	Cid      primitive.ObjectID `bson:"cid,omitempty" json:"cid,omitempty"`
+	Number   string             `bson:"number,omitempty" json:"number,omitempty"`
+	Cover    string             `bson:"cover,omitempty" json:"cover,omitempty"`
+	Name     string             `bson:"name,omitempty" json:"name,omitempty"`
+	Url      string             `bson:"url,omitempty" json:"url,omitempty"`
+	Desc     string             `bson:"desc,omitempty" json:"desc,omitempty"`
+	Document *Document          `bson:"document,omitempty" json:"document,omitempty"`
+
+	Clicks int `bson:"clicks,omitempty" json:"clicks,omitempty"`
+	Sort   int `bson:"sort,omitempty" json:"sort,omitempty"`
+
+	CreateTime time.Time `bson:"createTime,omitempty" json:"createTime,omitempty"`
+	UpdateTime time.Time `bson:"updateTime,omitempty" json:"updateTime,omitempty"`
+
+	// 1 上架 -1下架
+	State *int `bson:"state,omitempty" json:"state,omitempty"`
+}
+
+type Document struct {
+	RepairTime time.Time `bson:"repairTime,omitempty" json:"repairTime,omitempty"`
+	Before     []string  `bson:"before,omitempty" json:"before,omitempty"`
+	After      []string  `bson:"after,omitempty" json:"after,omitempty"`
+	Videos     []string  `bson:"videos,omitempty" json:"videos,omitempty"`
+	Audio      []string  `bson:"audio,omitempty" json:"audio,omitempty"`
+	IsPublic   *bool     `bson:"isPublic,omitempty" json:"isPublic,omitempty"`
+}

+ 15 - 0
src/db/model/role.go

@@ -0,0 +1,15 @@
+package model
+
+import (
+	"time"
+
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+type Role struct {
+	Id   primitive.ObjectID `bson:"_id,omitempty" json:"_id,omitempty"`
+	Name string             `bson:"name,omitempty" json:"name,omitempty"`
+
+	CreateTime time.Time `bson:"createTime,omitempty" json:"createTime,omitempty"`
+	UpdateTime time.Time `bson:"updateTime,omitempty" json:"updateTime,omitempty"`
+}

+ 7 - 5
src/db/model/user.go

@@ -8,16 +8,18 @@ import (
 
 type User struct {
 	Id        primitive.ObjectID `bson:"_id,omitempty" json:"_id,omitempty"`
-	Nid       string             `bson:"nid,omitempty" json:"nid,omitempty"`
+	RoleId    primitive.ObjectID `bson:"roleId,omitempty" json:"roleId,omitempty"`
 	LoginName string             `bson:"loginName,omitempty" json:"loginName,omitempty"`
 	Password  string             `bson:"password,omitempty" json:"password,omitempty"`
 	Avatar    string             `bson:"avatar,omitempty" json:"avatar,omitempty"`
-	// 学习总时长
-	// LearnTime int `bson:"learnTime,omitempty" json:"learnTime,omitempty"`
-	// student,teacher,admin
-	Roles      []string  `bson:"roles,omitempty" json:"roles,omitempty"`
+	Name      string             `bson:"name,omitempty" json:"name,omitempty"`
+	RoleInfo  *Role              `bson:"roleInfo,omitempty" json:"roleInfo,omitempty"`
+
 	CreateTime time.Time `bson:"createTime,omitempty" json:"createTime,omitempty"`
 	UpdateTime time.Time `bson:"updateTime,omitempty" json:"updateTime,omitempty"`
+
+	// 1 正常 -1禁用
+	State *int `bson:"state,omitempty" json:"state,omitempty"`
 }
 
 func (m *User) GetID() string {

+ 22 - 0
src/db/model/video.go

@@ -0,0 +1,22 @@
+package model
+
+import (
+	"time"
+
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+type Videos struct {
+	Id     primitive.ObjectID `bson:"_id,omitempty" json:"_id,omitempty"`
+	Cid    primitive.ObjectID `bson:"cid,omitempty" json:"cid,omitempty"`
+	Url    string             `bson:"url,omitempty" json:"url,omitempty"`
+	Name   string             `bson:"name,omitempty" json:"name,omitempty"`
+	Desc   string             `bson:"desc,omitempty" json:"desc,omitempty"`
+	Clicks int                `bson:"clicks,omitempty" json:"clicks,omitempty"`
+	Sort   int                `bson:"sort,omitempty" json:"sort,omitempty"`
+
+	CreateTime time.Time `bson:"createTime,omitempty" json:"createTime,omitempty"`
+	UpdateTime time.Time `bson:"updateTime,omitempty" json:"updateTime,omitempty"`
+	// 1 上架 -1下架
+	State *int `bson:"state,omitempty" json:"state,omitempty"`
+}

+ 26 - 0
src/db/model/vr.go

@@ -0,0 +1,26 @@
+package model
+
+import (
+	"time"
+
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+type Vr struct {
+	Id    primitive.ObjectID `bson:"_id,omitempty" json:"_id,omitempty"`
+	Cid   primitive.ObjectID `bson:"cid,omitempty" json:"cid,omitempty"`
+	Cover string             `bson:"cover,omitempty" json:"cover,omitempty"`
+	Name  string             `bson:"name,omitempty" json:"name,omitempty"`
+	Url   string             `bson:"url,omitempty" json:"url,omitempty"`
+	// scene custom
+	Type string `bson:"type,omitempty" json:"type,omitempty"`
+
+	Desc   string `bson:"desc,omitempty" json:"desc,omitempty"`
+	Clicks int    `bson:"clicks,omitempty" json:"clicks,omitempty"`
+	Sort   int    `bson:"sort,omitempty" json:"sort,omitempty"`
+
+	CreateTime time.Time `bson:"createTime,omitempty" json:"createTime,omitempty"`
+	UpdateTime time.Time `bson:"updateTime,omitempty" json:"updateTime,omitempty"`
+	// 1 上架 -1下架
+	State *int `bson:"state,omitempty" json:"state,omitempty"`
+}

+ 9 - 2
src/db/repo/repo.go

@@ -18,8 +18,15 @@ type RepoSession struct {
 }
 
 const (
-	CollectionUser        = "users"
-	CollectionExamHistory = "exam-history"
+	CollectionRoles      = "roles"
+	CollectionCategories = "categories"
+	CollectionUser       = "users"
+	CollectionHome       = "home"
+	CollectionImages     = "images"
+	CollectionVideos     = "videos"
+	CollectionRelics     = "relics"
+	CollectionVr         = "vr"
+	CollectionAr         = "ar"
 )
 
 type Map map[string]interface{}

+ 1 - 6
src/go.mod

@@ -9,7 +9,6 @@ require (
 	github.com/go-redis/redis/v8 v8.11.5
 	github.com/natefinch/lumberjack v2.0.0+incompatible
 	github.com/spf13/viper v1.9.0
-	github.com/xuri/excelize/v2 v2.8.1
 	go.mongodb.org/mongo-driver v1.11.1
 	go.uber.org/dig v1.12.0
 	go.uber.org/zap v1.17.0
@@ -41,7 +40,6 @@ require (
 	github.com/mitchellh/mapstructure v1.4.2 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
-	github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
 	github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
 	github.com/nats-io/jwt/v2 v2.3.0 // indirect
 	github.com/nats-io/nats.go v1.22.1 // indirect
@@ -49,19 +47,16 @@ require (
 	github.com/nats-io/nuid v1.0.1 // indirect
 	github.com/pelletier/go-toml v1.9.4 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
-	github.com/richardlehane/mscfb v1.0.4 // indirect
-	github.com/richardlehane/msoleps v1.0.3 // indirect
 	github.com/spf13/afero v1.6.0 // indirect
 	github.com/spf13/cast v1.4.1 // indirect
 	github.com/spf13/jwalterweatherman v1.1.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
+	github.com/stretchr/testify v1.8.4 // indirect
 	github.com/subosito/gotenv v1.2.0 // indirect
 	github.com/ugorji/go/codec v1.1.7 // indirect
 	github.com/xdg-go/pbkdf2 v1.0.0 // indirect
 	github.com/xdg-go/scram v1.1.2 // indirect
 	github.com/xdg-go/stringprep v1.0.4 // indirect
-	github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 // indirect
-	github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 // indirect
 	github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
 	go.uber.org/atomic v1.10.0 // indirect
 	go.uber.org/multierr v1.6.0 // indirect

+ 0 - 15
src/go.sum

@@ -890,8 +890,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
-github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
-github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
 github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
 github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
 github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
@@ -1039,11 +1037,6 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
 github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
 github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
-github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
-github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
-github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
-github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM=
-github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
 github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@@ -1176,12 +1169,6 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:
 github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
-github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 h1:Chd9DkqERQQuHpXjR/HSV1jLZA6uaoiwwH3vSuF3IW0=
-github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
-github.com/xuri/excelize/v2 v2.8.1 h1:pZLMEwK8ep+CLIUWpWmvW8IWE/yxqG0I1xcN6cVMGuQ=
-github.com/xuri/excelize/v2 v2.8.1/go.mod h1:oli1E4C3Pa5RXg1TBXn4ENCXDV5JUMlBluUhG7c+CEE=
-github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 h1:qhbILQo1K3mphbwKh1vNm4oGezE1eF9fQWmNiIpSfI4=
-github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
 github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
 github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk=
 github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4=
@@ -1311,8 +1298,6 @@ golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+o
 golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4=
-golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=