zk 2 jaren geleden
bovenliggende
commit
ff78022275
39 gewijzigde bestanden met toevoegingen van 2119 en 312 verwijderingen
  1. 2 0
      server/api/v1/autocode/enter.go
  2. 24 4
      server/api/v1/autocode/problem_info.go
  3. 143 0
      server/api/v1/autocode/problem_type.go
  4. 51 28
      server/api/v1/autocode/unit.go
  5. 6 2
      server/api/v1/system/sys_user.go
  6. 0 1
      server/api/v1/system/wechat.go
  7. 2 0
      server/initialize/gorm.go
  8. 3 0
      server/initialize/router.go
  9. 21 22
      server/model/autocode/problem_info.go
  10. 22 0
      server/model/autocode/problem_type.go
  11. 4 4
      server/model/autocode/request/problem_type.go
  12. 6 6
      server/model/autocode/unit.go
  13. 2 0
      server/router/autocode/enter.go
  14. 32 0
      server/router/autocode/problem_type.go
  15. 2 0
      server/service/autocode/enter.go
  16. 6 0
      server/service/autocode/problem_info.go
  17. 89 0
      server/service/autocode/problem_type.go
  18. 1 0
      server/service/autocode/read_count.go
  19. 49 10
      server/service/autocode/unit.go
  20. 97 0
      web/src/api/problemType.js
  21. 97 0
      web/src/api/unitHistory.js
  22. 51 0
      web/src/components/DictTag/index.vue
  23. 25 2
      web/src/main.js
  24. 81 0
      web/src/utils/dict/Dict.js
  25. 17 0
      web/src/utils/dict/DictConverter.js
  26. 13 0
      web/src/utils/dict/DictData.js
  27. 37 0
      web/src/utils/dict/DictMeta.js
  28. 51 0
      web/src/utils/dict/DictOptions.js
  29. 33 0
      web/src/utils/dict/index.js
  30. 87 87
      web/src/utils/request.js
  31. 15 0
      web/src/utils/zk.js
  32. 55 32
      web/src/view/place/place.vue
  33. 27 21
      web/src/view/problemInfo/proInfo.vue
  34. 90 72
      web/src/view/problemInfo/problemInfo.vue
  35. 243 0
      web/src/view/problemType/problemType.vue
  36. 82 0
      web/src/view/problemType/problemTypeForm.vue
  37. 123 21
      web/src/view/unit/unit.vue
  38. 336 0
      web/src/view/unitHistory/unitHistory.vue
  39. 94 0
      web/src/view/unitHistory/unitHistoryForm.vue

+ 2 - 0
server/api/v1/autocode/enter.go

@@ -8,5 +8,7 @@ type ApiGroup struct {
 	ProblemInfoApi
 	ReadCountApi
 	UnitApi
+	ProblemTypeApi
+	UnitHistoryApi
 	// Code generated by github.com/flipped-aurora/gin-vue-admin/server End; DO NOT EDIT.
 }

+ 24 - 4
server/api/v1/autocode/problem_info.go

@@ -12,6 +12,7 @@ import (
 	"github.com/silenceper/wechat/v2/officialaccount/message"
 	"go.uber.org/zap"
 	"strconv"
+	"strings"
 	"time"
 )
 
@@ -44,6 +45,24 @@ func (problemInfoApi *ProblemInfoApi) CreateProblemInfo(c *gin.Context) {
 		problemInfo.Region = place.Region
 	}
 
+	if problemInfo.UnitId != nil && *problemInfo.UnitId != 0 {
+		probleTypeIds := strings.Split(problemInfo.Matter, "|")
+		if len(probleTypeIds) > 0 {
+			_, proTypes := problemTypeService.GetProblemTypeIds(probleTypeIds)
+			var integral int
+			for _, proType := range proTypes {
+				inter := *proType.Integral
+				integral = integral + inter
+			}
+			problemInfo.Integral = &integral
+
+			_, unit := unitService.GetUnit(uint(*problemInfo.UnitId))
+			oldIntegral := *unit.UnitIntegral
+			nowIntegral := oldIntegral - integral
+			unit.UnitIntegral = &nowIntegral
+			unitService.UpdateUnitA(unit)
+		}
+	}
 	if err := problemInfoService.CreateProblemInfo(problemInfo); err != nil {
 		global.GVA_LOG.Error("创建失败!", zap.Any("err", err))
 		response.FailWithMessage("发布失败", c)
@@ -60,8 +79,9 @@ func (problemInfoApi *ProblemInfoApi) ExportExcel(c *gin.Context) {
 		global.GVA_LOG.Error("获取失败!", zap.Any("err", err))
 		response.FailWithMessage("获取失败", c)
 	} else {
-		_, dictList := service.ServiceGroupApp.SystemServiceGroup.DictionaryService.GetSysDictionaryDetailList()
-		err := service.ServiceGroupApp.ExampleServiceGroup.ExcelService.ProblemInfoList2Excel(list, filePath, dictList)
+		_, siteType := service.ServiceGroupApp.SystemServiceGroup.DictionaryService.GetSysDictionary("site_type", 0)
+		_, proList := problemTypeService.GetProblemTypeInfoListAll()
+		err := service.ServiceGroupApp.ExampleServiceGroup.ExcelService.ProblemInfoList2Excel(list, filePath, siteType, proList)
 		if err != nil {
 			global.GVA_LOG.Error("转换Excel失败!", zap.Any("err", err))
 			response.FailWithMessage("转换Excel失败", c)
@@ -189,7 +209,7 @@ func (problemInfoApi *ProblemInfoApi) FindProblemInfo(c *gin.Context) {
 		response.FailWithMessage("查询失败", c)
 	} else {
 		//param := reqMode.SysDictionarySearch{, request.PageInfo{PageSize: 9999, Page: 0}}
-		_, reproblemInfo.MatterList = service.ServiceGroupApp.SystemServiceGroup.DictionaryService.GetSysDictionaryDetail(reproblemInfo.SiteType)
+		_, reproblemInfo.MatterList, _ = service.ServiceGroupApp.AutoCodeServiceGroup.GetProblemTypeInfoListBySiteType(reproblemInfo.SiteType)
 		response.OkWithData(gin.H{"reproblemInfo": reproblemInfo}, c)
 	}
 }
@@ -213,7 +233,7 @@ func (problemInfoApi *ProblemInfoApi) FindProblemPInfo(c *gin.Context) {
 		//累加总阅读量
 		problemInfoService.UpdateProblemInfoCount(problemInfo.ID)
 		//param := reqMode.SysDictionarySearch{, request.PageInfo{PageSize: 9999, Page: 0}}
-		_, reproblemInfo.MatterList = service.ServiceGroupApp.SystemServiceGroup.DictionaryService.GetSysDictionaryDetail(reproblemInfo.SiteType)
+		_, reproblemInfo.MatterList, _ = service.ServiceGroupApp.AutoCodeServiceGroup.GetProblemTypeInfoListBySiteType(reproblemInfo.SiteType)
 		response.OkWithData(gin.H{"reproblemInfo": reproblemInfo}, c)
 	}
 }

+ 143 - 0
server/api/v1/autocode/problem_type.go

@@ -0,0 +1,143 @@
+package autocode
+
+import (
+	"github.com/flipped-aurora/gin-vue-admin/server/global"
+    "github.com/flipped-aurora/gin-vue-admin/server/model/autocode"
+    "github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
+    autocodeReq "github.com/flipped-aurora/gin-vue-admin/server/model/autocode/request"
+    "github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
+    "github.com/flipped-aurora/gin-vue-admin/server/service"
+    "github.com/gin-gonic/gin"
+    "go.uber.org/zap"
+)
+
+type ProblemTypeApi struct {
+}
+
+var problemTypeService = service.ServiceGroupApp.AutoCodeServiceGroup.ProblemTypeService
+
+
+// CreateProblemType 创建ProblemType
+// @Tags ProblemType
+// @Summary 创建ProblemType
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body autocode.ProblemType true "创建ProblemType"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /problemType/createProblemType [post]
+func (problemTypeApi *ProblemTypeApi) CreateProblemType(c *gin.Context) {
+	var problemType autocode.ProblemType
+	_ = c.ShouldBindJSON(&problemType)
+	if err := problemTypeService.CreateProblemType(problemType); err != nil {
+        global.GVA_LOG.Error("创建失败!", zap.Any("err", err))
+		response.FailWithMessage("创建失败", c)
+	} else {
+		response.OkWithMessage("创建成功", c)
+	}
+}
+
+// DeleteProblemType 删除ProblemType
+// @Tags ProblemType
+// @Summary 删除ProblemType
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body autocode.ProblemType true "删除ProblemType"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
+// @Router /problemType/deleteProblemType [delete]
+func (problemTypeApi *ProblemTypeApi) DeleteProblemType(c *gin.Context) {
+	var problemType autocode.ProblemType
+	_ = c.ShouldBindJSON(&problemType)
+	if err := problemTypeService.DeleteProblemType(problemType); err != nil {
+        global.GVA_LOG.Error("删除失败!", zap.Any("err", err))
+		response.FailWithMessage("删除失败", c)
+	} else {
+		response.OkWithMessage("删除成功", c)
+	}
+}
+
+// DeleteProblemTypeByIds 批量删除ProblemType
+// @Tags ProblemType
+// @Summary 批量删除ProblemType
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body request.IdsReq true "批量删除ProblemType"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"批量删除成功"}"
+// @Router /problemType/deleteProblemTypeByIds [delete]
+func (problemTypeApi *ProblemTypeApi) DeleteProblemTypeByIds(c *gin.Context) {
+	var IDS request.IdsReq
+    _ = c.ShouldBindJSON(&IDS)
+	if err := problemTypeService.DeleteProblemTypeByIds(IDS); err != nil {
+        global.GVA_LOG.Error("批量删除失败!", zap.Any("err", err))
+		response.FailWithMessage("批量删除失败", c)
+	} else {
+		response.OkWithMessage("批量删除成功", c)
+	}
+}
+
+// UpdateProblemType 更新ProblemType
+// @Tags ProblemType
+// @Summary 更新ProblemType
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body autocode.ProblemType true "更新ProblemType"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
+// @Router /problemType/updateProblemType [put]
+func (problemTypeApi *ProblemTypeApi) UpdateProblemType(c *gin.Context) {
+	var problemType autocode.ProblemType
+	_ = c.ShouldBindJSON(&problemType)
+	if err := problemTypeService.UpdateProblemType(problemType); err != nil {
+        global.GVA_LOG.Error("更新失败!", zap.Any("err", err))
+		response.FailWithMessage("更新失败", c)
+	} else {
+		response.OkWithMessage("更新成功", c)
+	}
+}
+
+// FindProblemType 用id查询ProblemType
+// @Tags ProblemType
+// @Summary 用id查询ProblemType
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data query autocode.ProblemType true "用id查询ProblemType"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
+// @Router /problemType/findProblemType [get]
+func (problemTypeApi *ProblemTypeApi) FindProblemType(c *gin.Context) {
+	var problemType autocode.ProblemType
+	_ = c.ShouldBindQuery(&problemType)
+	if err, reproblemType := problemTypeService.GetProblemType(problemType.ID); err != nil {
+        global.GVA_LOG.Error("查询失败!", zap.Any("err", err))
+		response.FailWithMessage("查询失败", c)
+	} else {
+		response.OkWithData(gin.H{"reproblemType": reproblemType}, c)
+	}
+}
+
+// GetProblemTypeList 分页获取ProblemType列表
+// @Tags ProblemType
+// @Summary 分页获取ProblemType列表
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data query autocodeReq.ProblemTypeSearch true "分页获取ProblemType列表"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /problemType/getProblemTypeList [get]
+func (problemTypeApi *ProblemTypeApi) GetProblemTypeList(c *gin.Context) {
+	var pageInfo autocodeReq.ProblemTypeSearch
+	_ = c.ShouldBindQuery(&pageInfo)
+	if err, list, total := problemTypeService.GetProblemTypeInfoList(pageInfo); err != nil {
+	    global.GVA_LOG.Error("获取失败!", zap.Any("err", err))
+        response.FailWithMessage("获取失败", c)
+    } else {
+        response.OkWithDetailed(response.PageResult{
+            List:     list,
+            Total:    total,
+            Page:     pageInfo.Page,
+            PageSize: pageInfo.PageSize,
+        }, "获取成功", c)
+    }
+}

+ 51 - 28
server/api/v1/autocode/unit.go

@@ -2,13 +2,14 @@ package autocode
 
 import (
 	"github.com/flipped-aurora/gin-vue-admin/server/global"
-    "github.com/flipped-aurora/gin-vue-admin/server/model/autocode"
-    "github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
-    autocodeReq "github.com/flipped-aurora/gin-vue-admin/server/model/autocode/request"
-    "github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
-    "github.com/flipped-aurora/gin-vue-admin/server/service"
-    "github.com/gin-gonic/gin"
-    "go.uber.org/zap"
+	"github.com/flipped-aurora/gin-vue-admin/server/model/autocode"
+	autocodeReq "github.com/flipped-aurora/gin-vue-admin/server/model/autocode/request"
+	"github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
+	"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
+	"github.com/flipped-aurora/gin-vue-admin/server/service"
+	"github.com/gin-gonic/gin"
+	"go.uber.org/zap"
+	"time"
 )
 
 type UnitApi struct {
@@ -16,7 +17,6 @@ type UnitApi struct {
 
 var unitService = service.ServiceGroupApp.AutoCodeServiceGroup.UnitService
 
-
 // CreateUnit 创建Unit
 // @Tags Unit
 // @Summary 创建Unit
@@ -29,11 +29,24 @@ var unitService = service.ServiceGroupApp.AutoCodeServiceGroup.UnitService
 func (unitApi *UnitApi) CreateUnit(c *gin.Context) {
 	var unit autocode.Unit
 	_ = c.ShouldBindJSON(&unit)
-	if err := unitService.CreateUnit(unit); err != nil {
-        global.GVA_LOG.Error("创建失败!", zap.Any("err", err))
-		response.FailWithMessage("创建失败", c)
-	} else {
+	if err, nowUnit := unitService.GetUnitTop(); err != nil {
+		//新建期数
+		unit.Period = time.Now().Format("20060102150405")
+		integral := 1000
+		unit.UnitIntegral = &integral
+		unit.UnitMaxIntegral = &integral
+		unitService.CreateUnit(unit)
 		response.OkWithMessage("创建成功", c)
+	} else {
+		unit.UnitIntegral = nowUnit.UnitMaxIntegral
+		unit.UnitMaxIntegral = nowUnit.UnitMaxIntegral
+		unit.Period = nowUnit.Period
+		if err := unitService.CreateUnit(unit); err != nil {
+			global.GVA_LOG.Error("创建失败!", zap.Any("err", err))
+			response.FailWithMessage("创建失败", c)
+		} else {
+			response.OkWithMessage("创建成功", c)
+		}
 	}
 }
 
@@ -50,7 +63,7 @@ func (unitApi *UnitApi) DeleteUnit(c *gin.Context) {
 	var unit autocode.Unit
 	_ = c.ShouldBindJSON(&unit)
 	if err := unitService.DeleteUnit(unit); err != nil {
-        global.GVA_LOG.Error("删除失败!", zap.Any("err", err))
+		global.GVA_LOG.Error("删除失败!", zap.Any("err", err))
 		response.FailWithMessage("删除失败", c)
 	} else {
 		response.OkWithMessage("删除成功", c)
@@ -68,9 +81,9 @@ func (unitApi *UnitApi) DeleteUnit(c *gin.Context) {
 // @Router /unit/deleteUnitByIds [delete]
 func (unitApi *UnitApi) DeleteUnitByIds(c *gin.Context) {
 	var IDS request.IdsReq
-    _ = c.ShouldBindJSON(&IDS)
+	_ = c.ShouldBindJSON(&IDS)
 	if err := unitService.DeleteUnitByIds(IDS); err != nil {
-        global.GVA_LOG.Error("批量删除失败!", zap.Any("err", err))
+		global.GVA_LOG.Error("批量删除失败!", zap.Any("err", err))
 		response.FailWithMessage("批量删除失败", c)
 	} else {
 		response.OkWithMessage("批量删除成功", c)
@@ -89,8 +102,18 @@ func (unitApi *UnitApi) DeleteUnitByIds(c *gin.Context) {
 func (unitApi *UnitApi) UpdateUnit(c *gin.Context) {
 	var unit autocode.Unit
 	_ = c.ShouldBindJSON(&unit)
-	if err := unitService.UpdateUnit(unit); err != nil {
-        global.GVA_LOG.Error("更新失败!", zap.Any("err", err))
+	//记录历史,更新所有
+	if err, units := unitService.GetUnitInfoListAll(); err != nil {
+		response.FailWithMessage("更新失败", c)
+		return
+	} else {
+		for _, temp := range units {
+			unitHistoryService.CreateUnitHistory(autocode.UnitHistory{UnitId: &temp.ID, UnitName: temp.UnitName, UnitIntegral: temp.UnitIntegral, UnitMaxIntegral: temp.UnitMaxIntegral, Period: temp.Period})
+		}
+	}
+
+	if err := unitService.UpdateUnitNext(unit); err != nil {
+		global.GVA_LOG.Error("更新失败!", zap.Any("err", err))
 		response.FailWithMessage("更新失败", c)
 	} else {
 		response.OkWithMessage("更新成功", c)
@@ -110,7 +133,7 @@ func (unitApi *UnitApi) FindUnit(c *gin.Context) {
 	var unit autocode.Unit
 	_ = c.ShouldBindQuery(&unit)
 	if err, reunit := unitService.GetUnit(unit.ID); err != nil {
-        global.GVA_LOG.Error("查询失败!", zap.Any("err", err))
+		global.GVA_LOG.Error("查询失败!", zap.Any("err", err))
 		response.FailWithMessage("查询失败", c)
 	} else {
 		response.OkWithData(gin.H{"reunit": reunit}, c)
@@ -130,14 +153,14 @@ func (unitApi *UnitApi) GetUnitList(c *gin.Context) {
 	var pageInfo autocodeReq.UnitSearch
 	_ = c.ShouldBindQuery(&pageInfo)
 	if err, list, total := unitService.GetUnitInfoList(pageInfo); err != nil {
-	    global.GVA_LOG.Error("获取失败!", zap.Any("err", err))
-        response.FailWithMessage("获取失败", c)
-    } else {
-        response.OkWithDetailed(response.PageResult{
-            List:     list,
-            Total:    total,
-            Page:     pageInfo.Page,
-            PageSize: pageInfo.PageSize,
-        }, "获取成功", c)
-    }
+		global.GVA_LOG.Error("获取失败!", zap.Any("err", err))
+		response.FailWithMessage("获取失败", c)
+	} else {
+		response.OkWithDetailed(response.PageResult{
+			List:     list,
+			Total:    total,
+			Page:     pageInfo.Page,
+			PageSize: pageInfo.PageSize,
+		}, "获取成功", c)
+	}
 }

+ 6 - 2
server/api/v1/system/sys_user.go

@@ -65,6 +65,10 @@ func (b *BaseApi) LoginWx(c *gin.Context) {
 			response.CodeMessage(2, "请等待审核", c)
 			return
 		}
+		if user.UnionId == "" {
+			user.UnionId = res.UnionID
+			userService.SetUserInfo(*user)
+		}
 		b.tokenNext(c, *user)
 	}
 }
@@ -78,7 +82,7 @@ func (b *BaseApi) RegisterWx(c *gin.Context) {
 	}
 	if err, sysUser := userService.GetUserInfoByUnionId(r.UnionId); err != nil {
 		authorityId := "100"
-		user := &system.SysUser{Username: r.Username, OpenId: r.OpenId, NickName: r.NickName, Password: utils.RandomString(10), HeaderImg: r.HeaderImg, AuthorityId: authorityId, Authorities: nil}
+		user := &system.SysUser{Username: r.Username, OpenId: r.OpenId, UnionId: r.UnionId, NickName: r.NickName, Password: utils.RandomString(10), HeaderImg: r.HeaderImg, AuthorityId: authorityId, Authorities: nil}
 		regErr, userReturn := userService.Register(*user)
 		if regErr != nil {
 			global.GVA_LOG.Error("注册失败!", zap.Any("err", err))
@@ -90,7 +94,7 @@ func (b *BaseApi) RegisterWx(c *gin.Context) {
 		sysUser.OpenId = r.OpenId
 		sysUser.NickName = r.NickName
 		sysUser.Username = r.Username
-		sysUser.OpenId = r.HeaderImg
+		sysUser.HeaderImg = r.HeaderImg
 		userService.SetUserInfo(sysUser)
 		response.CodeMessage(2, "资料已提交,请耐心等待审核!", c)
 	}

+ 0 - 1
server/api/v1/system/wechat.go

@@ -18,7 +18,6 @@ func (b *WechatApi) Req(c *gin.Context) {
 	server.SkipValidate(true)
 	//设置接收消息的处理方法
 	server.SetMessageHandler(func(msg *message.MixMessage) *message.Reply {
-		//TODO
 		//回复消息:演示回复用户发送的消息
 		if msg.Event == message.EventSubscribe {
 			global.GVA_LOG.Info("用户关注", zap.Any("openId", msg.FromUserName), zap.Any("msg", msg))

+ 2 - 0
server/initialize/gorm.go

@@ -54,6 +54,8 @@ func MysqlTables(db *gorm.DB) {
 		// Code generated by github.com/flipped-aurora/gin-vue-admin/server Begin; DO NOT EDIT.
 		autocode.AutoCodeExample{},
 		autocode.Unit{},
+		autocode.ProblemType{},
+		autocode.UnitHistory{},
 		// Code generated by github.com/flipped-aurora/gin-vue-admin/server End; DO NOT EDIT.
 	)
 	if err != nil {

+ 3 - 0
server/initialize/router.go

@@ -48,6 +48,7 @@ func Routers() *gin.Engine {
 		autocodeRouter.InitContentPRouter(PublicGroup)     // 内容详情
 		systemRouter.InitWechatRouter(PublicGroup)         // 微信公众号
 		autocodeRouter.InitReadCountRouter(PublicGroup)    // 查阅次数查看
+		autocodeRouter.ProblemTypePRouter(PublicGroup)     // 查阅次数查看
 	}
 	PrivateGroup := Router.Group("")
 	PrivateGroup.Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
@@ -73,6 +74,8 @@ func Routers() *gin.Engine {
 		autocodeRouter.InitProblemInfoRouter(PrivateGroup)
 		autocodeRouter.InitPlaceRouter(PrivateGroup)
 		autocodeRouter.InitUnitRouter(PrivateGroup)
+		autocodeRouter.InitProblemTypeRouter(PrivateGroup)
+		autocodeRouter.InitUnitHistoryRouter(PrivateGroup)
 		// Code generated by github.com/flipped-aurora/gin-vue-admin/server End; DO NOT EDIT.
 	}
 

+ 21 - 22
server/model/autocode/problem_info.go

@@ -3,33 +3,32 @@ package autocode
 
 import (
 	"github.com/flipped-aurora/gin-vue-admin/server/global"
-	"github.com/flipped-aurora/gin-vue-admin/server/model/system"
 )
 
 // ProblemInfo 结构体
 // 如果含有time.Time 请自行import time包
 type ProblemInfo struct {
 	global.GVA_MODEL
-	Oper       uint                 `json:"oper" form:"oper" gorm:"column:oper;comment:发布人;type:bigint"`
-	Handler    *int                 `json:"handler" form:"handler" gorm:"column:handler;comment:处理人;type:bigint"`
-	Imgs       string               `json:"imgs" form:"imgs" gorm:"column:imgs;comment:关联图片;type:varchar(2000);"`
-	Video      string               `json:"video" form:"video" gorm:"column:video;comment:关联视频;type:varchar(255);"`
-	SiteId     uint                 `json:"siteId" form:"siteId" gorm:"column:site_id;comment:站点id;type:bigint"`
-	SiteName   string               `json:"siteName" form:"siteName" gorm:"column:site_name;comment:站点id;type:bigint"`
-	Position   string               `json:"position" form:"position" gorm:"column:position;comment:经纬度;type:varchar(255);"`
-	Matter     string               `json:"matter" form:"matter" gorm:"column:matter;comment:问题列表;type:varchar(255);"`
-	SiteType   string               `json:"siteType" form:"siteType" gorm:"column:site_type;comment:站点类型;type:varchar(255);"`
-	Status     string               `json:"status" form:"status" gorm:"column:status;comment:处理状态;type:varchar(255);"`
-	Region     string               `json:"region" form:"region" gorm:"column:region;comment:区域;type:varchar(255);"`
-	HandImgs   string               `json:"handImgs" form:"handImgs" gorm:"column:hand_imgs;comment:处理图片;type:varchar(255);"`
-	HandText   string               `json:"handText" form:"handText" gorm:"column:hand_text;comment:处理内容;type:varchar(255);"`
-	Department string               `json:"department" form:"department" gorm:"column:department;comment:责任部门;type:varchar(255);"`
-	Remark     string               `json:"remark" form:"remark" gorm:"column:remark;comment:问题备注;type:varchar(600);"`
-	Count      *int                 `json:"count" form:"count" gorm:"default:0;column:count;comment:阅读次数;type:int);"`
-	Integral   *int                 `json:"integral" form:"integral" gorm:"default:0;column:integral;comment:积分;type:int);"`
-	UnitName   *int                 `json:"unitName" form:"unitName" gorm:"default:0;column:unit_name;comment:单位名称;type:varchar(255));"`
-	UnitId     *int                 `json:"unitId" form:"unitId" gorm:"default:0;column:unit_id;comment:单位id;type:int);"`
-	MatterList system.SysDictionary `json:"matterList" gorm:"-"`
+	Oper       uint        `json:"oper" form:"oper" gorm:"column:oper;comment:发布人;type:bigint"`
+	Handler    *int        `json:"handler" form:"handler" gorm:"column:handler;comment:处理人;type:bigint"`
+	Imgs       string      `json:"imgs" form:"imgs" gorm:"column:imgs;comment:关联图片;type:varchar(2000);"`
+	Video      string      `json:"video" form:"video" gorm:"column:video;comment:关联视频;type:varchar(255);"`
+	SiteId     uint        `json:"siteId" form:"siteId" gorm:"column:site_id;comment:站点id;type:bigint"`
+	SiteName   string      `json:"siteName" form:"siteName" gorm:"column:site_name;comment:站点id;type:bigint"`
+	Position   string      `json:"position" form:"position" gorm:"column:position;comment:经纬度;type:varchar(255);"`
+	Matter     string      `json:"matter" form:"matter" gorm:"column:matter;comment:问题列表;type:varchar(255);"`
+	SiteType   *int        `json:"siteType" form:"siteType" gorm:"column:site_type;comment:站点类型;type:int;"`
+	Status     string      `json:"status" form:"status" gorm:"column:status;comment:处理状态;type:varchar(255);"`
+	Region     string      `json:"region" form:"region" gorm:"column:region;comment:区域;type:varchar(255);"`
+	HandImgs   string      `json:"handImgs" form:"handImgs" gorm:"column:hand_imgs;comment:处理图片;type:varchar(255);"`
+	HandText   string      `json:"handText" form:"handText" gorm:"column:hand_text;comment:处理内容;type:varchar(255);"`
+	Department string      `json:"department" form:"department" gorm:"column:department;comment:责任部门;type:varchar(255);"`
+	Remark     string      `json:"remark" form:"remark" gorm:"column:remark;comment:问题备注;type:varchar(600);"`
+	Count      *int        `json:"count" form:"count" gorm:"default:0;column:count;comment:阅读次数;type:int);"`
+	Integral   *int        `json:"integral" form:"integral" gorm:"default:0;column:integral;comment:积分;type:int);"`
+	UnitName   string      `json:"unitName" form:"unitName" gorm:"column:unit_name;comment:单位名称;type:varchar(255));"`
+	UnitId     *int        `json:"unitId" form:"unitId" gorm:"default:0;column:unit_id;comment:单位id;type:int);"`
+	MatterList interface{} `json:"matterList" gorm:"-"`
 }
 
 type ProblemInfo1 struct {
@@ -51,7 +50,7 @@ type ProblemInfo1 struct {
 	Remark     string `json:"remark" form:"remark" gorm:"column:remark;comment:问题备注;type:varchar(600);"`
 	Count      *int   `json:"count" form:"count" gorm:"default:0;column:count;comment:阅读次数;type:int);"`
 	Integral   *int   `json:"integral" form:"integral" gorm:"default:0;column:integral;comment:积分;type:int);"`
-	UnitName   *int   `json:"unitName" form:"unitName" gorm:"default:0;column:unit_name;comment:单位名称;type:varchar(255));"`
+	UnitName   string `json:"unitName" form:"unitName" gorm:"column:unit_name;comment:单位名称;type:varchar(255));"`
 	UnitId     *int   `json:"unitId" form:"unitId" gorm:"default:0;column:unit_id;comment:单位id;type:int);"`
 }
 

+ 22 - 0
server/model/autocode/problem_type.go

@@ -0,0 +1,22 @@
+// 自动生成模板ProblemType
+package autocode
+
+import (
+	"github.com/flipped-aurora/gin-vue-admin/server/global"
+)
+
+// ProblemType 结构体
+// 如果含有time.Time 请自行import time包
+type ProblemType struct {
+      global.GVA_MODEL
+      SiteType  *int `json:"siteType" form:"siteType" gorm:"column:site_type;comment:站点类型;type:int"`
+      Problem  string `json:"problem" form:"problem" gorm:"column:problem;comment:问题;type:varchar(255);"`
+      Integral  *int `json:"integral" form:"integral" gorm:"column:integral;comment:分数;type:int"`
+}
+
+
+// TableName ProblemType 表名
+func (ProblemType) TableName() string {
+  return "problem_type"
+}
+

+ 4 - 4
server/model/request/read_count.go → server/model/autocode/request/problem_type.go

@@ -5,7 +5,7 @@ import (
 	"github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
 )
 
-type ReadCountSearch struct{
-    autocode.ReadCount
-    request.PageInfo
-}
+type ProblemTypeSearch struct {
+	autocode.ProblemType
+	request.PageInfo
+}

+ 6 - 6
server/model/autocode/unit.go

@@ -8,14 +8,14 @@ import (
 // Unit 结构体
 // 如果含有time.Time 请自行import time包
 type Unit struct {
-      global.GVA_MODEL
-      UnitName  string `json:"unitName" form:"unitName" gorm:"column:unit_name;comment:单位名称;type:varchar(200);"`
-      UnitIntegral  *int `json:"unitIntegral" form:"unitIntegral" gorm:"column:unit_integral;comment:现有积分;type:int"`
+	global.GVA_MODEL
+	UnitName        string `json:"unitName" form:"unitName" gorm:"column:unit_name;comment:单位名称;type:varchar(200);"`
+	Period          string `json:"period" form:"period" gorm:"column:period;comment:期编号;type:varchar(40);"`
+	UnitIntegral    *int   `json:"unitIntegral" form:"unitIntegral" gorm:"column:unit_integral;comment:现有积分;type:int"`
+	UnitMaxIntegral *int   `json:"unitMaxIntegral" form:"unitMaxIntegral" gorm:"column:unit_max_integral;comment:满分;type:int"`
 }
 
-
 // TableName Unit 表名
 func (Unit) TableName() string {
-  return "unit"
+	return "unit"
 }
-

+ 2 - 0
server/router/autocode/enter.go

@@ -8,5 +8,7 @@ type RouterGroup struct {
 	ProblemInfoRouter
 	ReadCountRouter
 	UnitRouter
+	ProblemTypeRouter
+	UnitHistoryRouter
 	// Code generated by github.com/flipped-aurora/gin-vue-admin/server End; DO NOT EDIT.
 }

+ 32 - 0
server/router/autocode/problem_type.go

@@ -0,0 +1,32 @@
+package autocode
+
+import (
+	"github.com/flipped-aurora/gin-vue-admin/server/api/v1"
+	"github.com/flipped-aurora/gin-vue-admin/server/middleware"
+	"github.com/gin-gonic/gin"
+)
+
+type ProblemTypeRouter struct {
+}
+
+// InitProblemTypeRouter 初始化 ProblemType 路由信息
+func (s *ProblemTypeRouter) InitProblemTypeRouter(Router *gin.RouterGroup) {
+	problemTypeRouter := Router.Group("problemType").Use(middleware.OperationRecord())
+	var problemTypeApi = v1.ApiGroupApp.AutoCodeApiGroup.ProblemTypeApi
+	{
+		problemTypeRouter.POST("createProblemType", problemTypeApi.CreateProblemType)             // 新建ProblemType
+		problemTypeRouter.DELETE("deleteProblemType", problemTypeApi.DeleteProblemType)           // 删除ProblemType
+		problemTypeRouter.DELETE("deleteProblemTypeByIds", problemTypeApi.DeleteProblemTypeByIds) // 批量删除ProblemType
+		problemTypeRouter.PUT("updateProblemType", problemTypeApi.UpdateProblemType)              // 更新ProblemType
+		problemTypeRouter.GET("findProblemType", problemTypeApi.FindProblemType)                  // 根据ID获取ProblemType
+		problemTypeRouter.GET("getProblemTypeList", problemTypeApi.GetProblemTypeList)            // 获取ProblemType列表
+	}
+}
+
+func (s *ContentRouter) ProblemTypePRouter(Router *gin.RouterGroup) {
+	problemTypeRouter := Router.Group("problemType").Use(middleware.OperationRecord())
+	var problemTypeApi = v1.ApiGroupApp.AutoCodeApiGroup.ProblemTypeApi
+	{
+		problemTypeRouter.GET("findProblemTypeList", problemTypeApi.GetProblemTypeList)
+	}
+}

+ 2 - 0
server/service/autocode/enter.go

@@ -8,5 +8,7 @@ type ServiceGroup struct {
 	ProblemInfoService
 	ReadCountService
 	UnitService
+	ProblemTypeService
+	UnitHistoryService
 	// Code generated by github.com/flipped-aurora/gin-vue-admin/server End; DO NOT EDIT.
 }

+ 6 - 0
server/service/autocode/problem_info.go

@@ -61,12 +61,18 @@ func (problemInfoService *ProblemInfoService) GetProblemInfoInfoList(info autoCo
 	if info.SiteType != "" {
 		db.Where("site_type=?", info.SiteType)
 	}
+	if info.UnitId != nil && *info.UnitId != 0 {
+		db.Where("unit_id=?", info.UnitId)
+	}
 	if info.Status != "" {
 		db.Where("status=?", info.Status)
 	}
 	if info.Oper != 0 {
 		db.Where("oper=?", info.Oper)
 	}
+	if !info.CreatedAtStart.IsZero() && !info.CreatedAtEnd.IsZero() {
+		db.Where("created_at between ? and ?", info.CreatedAtStart, info.CreatedAtEnd)
+	}
 	var problemInfos []autocode.ProblemInfo
 	// 如果有条件搜索 下方会自动创建搜索语句
 	err = db.Count(&total).Error

+ 89 - 0
server/service/autocode/problem_type.go

@@ -0,0 +1,89 @@
+package autocode
+
+import (
+	"github.com/flipped-aurora/gin-vue-admin/server/global"
+	"github.com/flipped-aurora/gin-vue-admin/server/model/autocode"
+	autoCodeReq "github.com/flipped-aurora/gin-vue-admin/server/model/autocode/request"
+	"github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
+)
+
+type ProblemTypeService struct {
+}
+
+// CreateProblemType 创建ProblemType记录
+// Author [piexlmax](https://github.com/piexlmax)
+func (problemTypeService *ProblemTypeService) CreateProblemType(problemType autocode.ProblemType) (err error) {
+	err = global.GVA_DB.Create(&problemType).Error
+	return err
+}
+
+// DeleteProblemType 删除ProblemType记录
+// Author [piexlmax](https://github.com/piexlmax)
+func (problemTypeService *ProblemTypeService) DeleteProblemType(problemType autocode.ProblemType) (err error) {
+	err = global.GVA_DB.Delete(&problemType).Error
+	return err
+}
+
+// DeleteProblemTypeByIds 批量删除ProblemType记录
+// Author [piexlmax](https://github.com/piexlmax)
+func (problemTypeService *ProblemTypeService) DeleteProblemTypeByIds(ids request.IdsReq) (err error) {
+	err = global.GVA_DB.Delete(&[]autocode.ProblemType{}, "id in ?", ids.Ids).Error
+	return err
+}
+
+// UpdateProblemType 更新ProblemType记录
+// Author [piexlmax](https://github.com/piexlmax)
+func (problemTypeService *ProblemTypeService) UpdateProblemType(problemType autocode.ProblemType) (err error) {
+	err = global.GVA_DB.Save(&problemType).Error
+	return err
+}
+
+// GetProblemType 根据id获取ProblemType记录
+// Author [piexlmax](https://github.com/piexlmax)
+func (problemTypeService *ProblemTypeService) GetProblemType(id uint) (err error, problemType autocode.ProblemType) {
+	err = global.GVA_DB.Where("id = ?", id).First(&problemType).Error
+	return
+}
+
+func (problemTypeService *ProblemTypeService) GetProblemTypeIds(id []string) (err error, problemType []autocode.ProblemType) {
+	var problemTypes []autocode.ProblemType
+	err = global.GVA_DB.Where("id in ?", id).Find(&problemTypes).Error
+	return err, problemTypes
+}
+
+// GetProblemTypeInfoList 分页获取ProblemType记录
+// Author [piexlmax](https://github.com/piexlmax)
+func (problemTypeService *ProblemTypeService) GetProblemTypeInfoList(info autoCodeReq.ProblemTypeSearch) (err error, list interface{}, total int64) {
+	limit := info.PageSize
+	offset := info.PageSize * (info.Page - 1)
+	// 创建db
+	db := global.GVA_DB.Model(&autocode.ProblemType{})
+	if info.SiteType != nil {
+		db.Where("site_type = ?", info.SiteType)
+	}
+	var problemTypes []autocode.ProblemType
+	// 如果有条件搜索 下方会自动创建搜索语句
+	err = db.Count(&total).Error
+	err = db.Limit(limit).Offset(offset).Find(&problemTypes).Error
+	return err, problemTypes, total
+}
+
+func (problemTypeService *ProblemTypeService) GetProblemTypeInfoListBySiteType(siteType *int) (err error, list interface{}, total int64) {
+	// 创建db
+	db := global.GVA_DB.Model(&autocode.ProblemType{})
+	db.Where("site_type = ?", siteType)
+	var problemTypes []autocode.ProblemType
+	// 如果有条件搜索 下方会自动创建搜索语句
+	err = db.Count(&total).Error
+	err = db.Find(&problemTypes).Error
+	return err, problemTypes, total
+}
+
+func (problemTypeService *ProblemTypeService) GetProblemTypeInfoListAll() (err error, list []autocode.ProblemType) {
+	// 创建db
+	db := global.GVA_DB.Model(&autocode.ProblemType{})
+	var problemTypes []autocode.ProblemType
+	// 如果有条件搜索 下方会自动创建搜索语句
+	err = db.Find(&problemTypes).Order("site_type").Error
+	return err, problemTypes
+}

+ 1 - 0
server/service/autocode/read_count.go

@@ -64,6 +64,7 @@ func (readCountService *ReadCountService) GetReadCountInfoList(info autoCodeReq.
 	// 创建db
 	db := global.GVA_DB.Model(&autocode.ReadCount{})
 	var readCounts []autocode.ReadCount
+	db.Where("problem_id = ?", info.ProblemId)
 	// 如果有条件搜索 下方会自动创建搜索语句
 	err = db.Count(&total).Error
 	err = db.Limit(limit).Offset(offset).Find(&readCounts).Error

+ 49 - 10
server/service/autocode/unit.go

@@ -3,8 +3,10 @@ package autocode
 import (
 	"github.com/flipped-aurora/gin-vue-admin/server/global"
 	"github.com/flipped-aurora/gin-vue-admin/server/model/autocode"
+	autoCodeReq "github.com/flipped-aurora/gin-vue-admin/server/model/autocode/request"
 	"github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
-    autoCodeReq "github.com/flipped-aurora/gin-vue-admin/server/model/autocode/request"
+	"gorm.io/gorm"
+	"time"
 )
 
 type UnitService struct {
@@ -19,42 +21,79 @@ func (unitService *UnitService) CreateUnit(unit autocode.Unit) (err error) {
 
 // DeleteUnit 删除Unit记录
 // Author [piexlmax](https://github.com/piexlmax)
-func (unitService *UnitService)DeleteUnit(unit autocode.Unit) (err error) {
+func (unitService *UnitService) DeleteUnit(unit autocode.Unit) (err error) {
 	err = global.GVA_DB.Delete(&unit).Error
 	return err
 }
 
 // DeleteUnitByIds 批量删除Unit记录
 // Author [piexlmax](https://github.com/piexlmax)
-func (unitService *UnitService)DeleteUnitByIds(ids request.IdsReq) (err error) {
-	err = global.GVA_DB.Delete(&[]autocode.Unit{},"id in ?",ids.Ids).Error
+func (unitService *UnitService) DeleteUnitByIds(ids request.IdsReq) (err error) {
+	err = global.GVA_DB.Delete(&[]autocode.Unit{}, "id in ?", ids.Ids).Error
 	return err
 }
 
 // UpdateUnit 更新Unit记录
 // Author [piexlmax](https://github.com/piexlmax)
-func (unitService *UnitService)UpdateUnit(unit autocode.Unit) (err error) {
+func (unitService *UnitService) UpdateUnit(unit autocode.Unit) (err error) {
+	now := *unit.UnitIntegral
+	now = now * 10
+	unit.UnitIntegral = &now
+	err = global.GVA_DB.Save(&unit).Error
+	return err
+}
+
+// UpdateUnit 开始下期
+// Author [piexlmax](https://github.com/piexlmax)
+func (unitService *UnitService) UpdateUnitNext(unit autocode.Unit) (err error) {
+	//开始下一期
+	now := *unit.UnitIntegral
+	now = now * 10
+	unit.UnitIntegral = &now
+	global.GVA_DB.Session(&gorm.Session{
+		AllowGlobalUpdate: true,
+	}).Model(&unit).Updates(&autocode.Unit{UnitMaxIntegral: unit.UnitIntegral, UnitIntegral: unit.UnitIntegral, Period: time.Now().Format("20060102150405")})
+	return err
+}
+
+func (unitService *UnitService) UpdateUnitA(unit autocode.Unit) (err error) {
 	err = global.GVA_DB.Save(&unit).Error
 	return err
 }
 
 // GetUnit 根据id获取Unit记录
 // Author [piexlmax](https://github.com/piexlmax)
-func (unitService *UnitService)GetUnit(id uint) (err error, unit autocode.Unit) {
+func (unitService *UnitService) GetUnit(id uint) (err error, unit autocode.Unit) {
 	err = global.GVA_DB.Where("id = ?", id).First(&unit).Error
 	return
 }
 
+func (unitService *UnitService) GetUnitTop() (err error, unit autocode.Unit) {
+	top := autocode.Unit{}
+	err = global.GVA_DB.First(&top).Error
+	return err, top
+}
+
 // GetUnitInfoList 分页获取Unit记录
 // Author [piexlmax](https://github.com/piexlmax)
-func (unitService *UnitService)GetUnitInfoList(info autoCodeReq.UnitSearch) (err error, list interface{}, total int64) {
+func (unitService *UnitService) GetUnitInfoList(info autoCodeReq.UnitSearch) (err error, list interface{}, total int64) {
 	limit := info.PageSize
 	offset := info.PageSize * (info.Page - 1)
-    // 创建db
+	// 创建db
 	db := global.GVA_DB.Model(&autocode.Unit{})
-    var units []autocode.Unit
-    // 如果有条件搜索 下方会自动创建搜索语句
+	if info.UnitName != "" {
+		db.Where("unit_name = ?", info.UnitName)
+	}
+	var units []autocode.Unit
+	// 如果有条件搜索 下方会自动创建搜索语句
 	err = db.Count(&total).Error
 	err = db.Limit(limit).Offset(offset).Find(&units).Error
 	return err, units, total
 }
+
+func (unitService *UnitService) GetUnitInfoListAll() (err error, list []autocode.Unit) {
+	var units []autocode.Unit
+	// 创建db
+	err = global.GVA_DB.Model(&autocode.Unit{}).Find(&units).Error
+	return err, units
+}

+ 97 - 0
web/src/api/problemType.js

@@ -0,0 +1,97 @@
+import service from '@/utils/request'
+
+// @Tags ProblemType
+// @Summary 创建ProblemType
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body model.ProblemType true "创建ProblemType"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /problemType/createProblemType [post]
+export const createProblemType = (data) => {
+  return service({
+    url: '/problemType/createProblemType',
+    method: 'post',
+    data
+  })
+}
+
+// @Tags ProblemType
+// @Summary 删除ProblemType
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body model.ProblemType true "删除ProblemType"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
+// @Router /problemType/deleteProblemType [delete]
+export const deleteProblemType = (data) => {
+  return service({
+    url: '/problemType/deleteProblemType',
+    method: 'delete',
+    data
+  })
+}
+
+// @Tags ProblemType
+// @Summary 删除ProblemType
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body request.IdsReq true "批量删除ProblemType"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
+// @Router /problemType/deleteProblemType [delete]
+export const deleteProblemTypeByIds = (data) => {
+  return service({
+    url: '/problemType/deleteProblemTypeByIds',
+    method: 'delete',
+    data
+  })
+}
+
+// @Tags ProblemType
+// @Summary 更新ProblemType
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body model.ProblemType true "更新ProblemType"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
+// @Router /problemType/updateProblemType [put]
+export const updateProblemType = (data) => {
+  return service({
+    url: '/problemType/updateProblemType',
+    method: 'put',
+    data
+  })
+}
+
+// @Tags ProblemType
+// @Summary 用id查询ProblemType
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data query model.ProblemType true "用id查询ProblemType"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
+// @Router /problemType/findProblemType [get]
+export const findProblemType = (params) => {
+  return service({
+    url: '/problemType/findProblemType',
+    method: 'get',
+    params
+  })
+}
+
+// @Tags ProblemType
+// @Summary 分页获取ProblemType列表
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data query request.PageInfo true "分页获取ProblemType列表"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /problemType/getProblemTypeList [get]
+export const getProblemTypeList = (params) => {
+  return service({
+    url: '/problemType/getProblemTypeList',
+    method: 'get',
+    params
+  })
+}

+ 97 - 0
web/src/api/unitHistory.js

@@ -0,0 +1,97 @@
+import service from '@/utils/request'
+
+// @Tags UnitHistory
+// @Summary 创建UnitHistory
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body model.UnitHistory true "创建UnitHistory"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /unitHistory/createUnitHistory [post]
+export const createUnitHistory = (data) => {
+  return service({
+    url: '/unitHistory/createUnitHistory',
+    method: 'post',
+    data
+  })
+}
+
+// @Tags UnitHistory
+// @Summary 删除UnitHistory
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body model.UnitHistory true "删除UnitHistory"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
+// @Router /unitHistory/deleteUnitHistory [delete]
+export const deleteUnitHistory = (data) => {
+  return service({
+    url: '/unitHistory/deleteUnitHistory',
+    method: 'delete',
+    data
+  })
+}
+
+// @Tags UnitHistory
+// @Summary 删除UnitHistory
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body request.IdsReq true "批量删除UnitHistory"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
+// @Router /unitHistory/deleteUnitHistory [delete]
+export const deleteUnitHistoryByIds = (data) => {
+  return service({
+    url: '/unitHistory/deleteUnitHistoryByIds',
+    method: 'delete',
+    data
+  })
+}
+
+// @Tags UnitHistory
+// @Summary 更新UnitHistory
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body model.UnitHistory true "更新UnitHistory"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
+// @Router /unitHistory/updateUnitHistory [put]
+export const updateUnitHistory = (data) => {
+  return service({
+    url: '/unitHistory/updateUnitHistory',
+    method: 'put',
+    data
+  })
+}
+
+// @Tags UnitHistory
+// @Summary 用id查询UnitHistory
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data query model.UnitHistory true "用id查询UnitHistory"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
+// @Router /unitHistory/findUnitHistory [get]
+export const findUnitHistory = (params) => {
+  return service({
+    url: '/unitHistory/findUnitHistory',
+    method: 'get',
+    params
+  })
+}
+
+// @Tags UnitHistory
+// @Summary 分页获取UnitHistory列表
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data query request.PageInfo true "分页获取UnitHistory列表"
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /unitHistory/getUnitHistoryList [get]
+export const getUnitHistoryList = (params) => {
+  return service({
+    url: '/unitHistory/getUnitHistoryList',
+    method: 'get',
+    params
+  })
+}

+ 51 - 0
web/src/components/DictTag/index.vue

@@ -0,0 +1,51 @@
+<template>
+  <div>
+    <template v-for="(item, index) in options">
+      <template v-if="values.includes(item.value.toString())">
+        <span
+          v-if="item.raw.listClass == 'default' || item.raw.listClass == ''"
+          :key="item.value"
+          :index="index"
+          :class="item.raw.cssClass"
+        >{{ item.label }}</span>
+        <el-tag
+          v-else
+          :key="item.value"
+          :disable-transitions="true"
+          :index="index"
+          :type="item.raw.listClass == 'primary' ? '' : item.raw.listClass"
+          :class="item.raw.cssClass"
+        >
+          {{ item.label }}
+        </el-tag>
+      </template>
+    </template>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'DictTag',
+  props: {
+    options: {
+      type: Array,
+      default: null,
+    },
+    value: [Number, String, Array],
+  },
+  computed: {
+    values() {
+      if (this.value !== null && typeof this.value !== 'undefined') {
+        return Array.isArray(this.value) ? this.value : [String(this.value)]
+      } else {
+        return []
+      }
+    },
+  },
+}
+</script>
+<style scoped>
+.el-tag + .el-tag {
+  margin-left: 10px;
+}
+</style>

+ 25 - 2
web/src/main.js

@@ -1,3 +1,4 @@
+// import Vue from 'vue'
 import { createApp } from 'vue'
 import 'element-plus/dist/index.css'
 import ElementPlus from 'element-plus'
@@ -9,14 +10,36 @@ import router from '@/router/index'
 import { run } from '@/core/gin-vue-admin.js'
 import '@/permission'
 import { store } from '@/store/index'
-
+// 字典标签组件
+import DictTag from '@/components/DictTag/index.vue'
 import { auth } from '@/directive/auth'
-
 import App from './App.vue'
+
 const app = createApp(App)
+import { findSysDictionary as getDicts } from '@/api/sysDictionary'
+import DataDict from '@/utils/dict'
+
+// 字典数据组件
+
+// Vue.prototype.getDicts = getDicts
+//
+
 run(app)
 auth(app)
 app.config.productionTip = false
+app.config.globalProperties.$getDicts = getDicts
+app.component('DictTag', DictTag)
+app.use(DataDict, {
+  metas: {
+    '*': {
+      labelField: 'label',
+      valueField: 'value',
+      request(dictMeta) {
+        return getDicts({ type: dictMeta.type }).then(res => res.data)
+      },
+    },
+  },
+})
 app.use(store).use(router).use(ElementPlus, { locale: zhCn }).mount('#app')
 
 export default app

+ 81 - 0
web/src/utils/dict/Dict.js

@@ -0,0 +1,81 @@
+import { mergeRecursive } from '@/utils/zk'
+import DictMeta from './DictMeta'
+import DictData from './DictData'
+
+const DEFAULT_DICT_OPTIONS = {
+  types: [],
+}
+
+/**
+ * @classdesc 字典
+ * @property {Object} label 标签对象,内部属性名为字典类型名称
+ * @property {Object} dict 字段数组,内部属性名为字典类型名称
+ * @property {Array.<DictMeta>} _dictMetas 字典元数据数组
+ */
+export default class Dict {
+  constructor() {
+    this.owner = null
+    this.label = {}
+    this.type = {}
+  }
+
+  init(options) {
+    if (options instanceof Array) {
+      options = { types: options }
+    }
+    const opts = mergeRecursive(DEFAULT_DICT_OPTIONS, options)
+    if (opts.types === undefined) {
+      throw new Error('need dict types')
+    }
+    const ps = []
+    this._dictMetas = opts.types.map(t => DictMeta.parse(t))
+    this._dictMetas.forEach(dictMeta => {
+      const type = dictMeta.type
+      this.label[type] = {}
+      this.type[type] = []
+      if (dictMeta.lazy) {
+        return
+      }
+      ps.push(loadDict(this, dictMeta))
+    })
+    return Promise.all(ps)
+  }
+
+  /**
+   * 重新加载字典
+   * @param {String} type 字典类型
+   */
+  reloadDict(type) {
+    const dictMeta = this._dictMetas.find(e => e.type === type)
+    if (dictMeta === undefined) {
+      return Promise.reject(`the dict meta of ${type} was not found`)
+    }
+    return loadDict(this, dictMeta)
+  }
+}
+
+/**
+ * 加载字典
+ * @param {Dict} dict 字典
+ * @param {DictMeta} dictMeta 字典元数据
+ * @returns {Promise}
+ */
+function loadDict(dict, dictMeta) {
+  return dictMeta.request(dictMeta)
+    .then(response => {
+      const type = dictMeta.type
+      let dicts = dictMeta.responseConverter(response, dictMeta)
+      if (!(dicts instanceof Array)) {
+        console.error('the return of responseConverter must be Array.<DictData>')
+        dicts = []
+      } else if (dicts.filter(d => d instanceof DictData).length !== dicts.length) {
+        console.error('the type of elements in dicts must be DictData')
+        dicts = []
+      }
+      dict.type[type].splice(0, Number.MAX_SAFE_INTEGER, ...dicts)
+      dicts.forEach(d => {
+        dict.label[type][d.value] = d.label
+      })
+      return dicts
+    })
+}

+ 17 - 0
web/src/utils/dict/DictConverter.js

@@ -0,0 +1,17 @@
+import DictOptions from './DictOptions'
+import DictData from './DictData'
+
+export default function(dict, dictMeta) {
+  const label = determineDictField(dict, dictMeta.labelField, ...DictOptions.DEFAULT_LABEL_FIELDS)
+  const value = determineDictField(dict, dictMeta.valueField, ...DictOptions.DEFAULT_VALUE_FIELDS)
+  return new DictData(dict[label], dict[value], dict)
+}
+
+/**
+ * 确定字典字段
+ * @param {DictData} dict
+ * @param  {...String} fields
+ */
+function determineDictField(dict, ...fields) {
+  return fields.find(f => Object.prototype.hasOwnProperty.call(dict, f))
+}

+ 13 - 0
web/src/utils/dict/DictData.js

@@ -0,0 +1,13 @@
+/**
+ * @classdesc 字典数据
+ * @property {String} label 标签
+ * @property {*} value 标签
+ * @property {Object} raw 原始数据
+ */
+export default class DictData {
+  constructor(label, value, raw) {
+    this.label = label
+    this.value = value
+    this.raw = raw
+  }
+}

+ 37 - 0
web/src/utils/dict/DictMeta.js

@@ -0,0 +1,37 @@
+import { mergeRecursive } from '@/utils/zk'
+import DictOptions from './DictOptions'
+
+/**
+ * @classdesc 字典元数据
+ * @property {String} type 类型
+ * @property {Function} request 请求
+ * @property {String} label 标签字段
+ * @property {String} value 值字段
+ */
+export default class DictMeta {
+  constructor(options) {
+    this.type = options.type
+    this.request = options.request,
+    this.responseConverter = options.responseConverter
+    this.labelField = options.labelField
+    this.valueField = options.valueField
+    this.lazy = options.lazy === true
+  }
+}
+
+/**
+ * 解析字典元数据
+ * @param {Object} options
+ * @returns {DictMeta}
+ */
+DictMeta.parse = function(options) {
+  let opts = null
+  if (typeof options === 'string') {
+    opts = DictOptions.metas[options] || {}
+    opts.type = options
+  } else if (typeof options === 'object') {
+    opts = options
+  }
+  opts = mergeRecursive(DictOptions.metas['*'], opts)
+  return new DictMeta(opts)
+}

+ 51 - 0
web/src/utils/dict/DictOptions.js

@@ -0,0 +1,51 @@
+import { mergeRecursive } from '@/utils/zk'
+import dictConverter from './DictConverter'
+
+export const options = {
+  metas: {
+    '*': {
+      /**
+       * 字典请求,方法签名为function(dictMeta: DictMeta): Promise
+       */
+      request: (dictMeta) => {
+        console.log(`load dict ${dictMeta.type}`)
+        return Promise.resolve([])
+      },
+      /**
+       * 字典响应数据转换器,方法签名为function(response: Object, dictMeta: DictMeta): DictData
+       */
+      responseConverter,
+      labelField: 'label',
+      valueField: 'value',
+    },
+  },
+  /**
+   * 默认标签字段
+   */
+  DEFAULT_LABEL_FIELDS: ['label', 'name', 'title'],
+  /**
+   * 默认值字段
+   */
+  DEFAULT_VALUE_FIELDS: ['value', 'id', 'uid', 'key'],
+}
+
+/**
+ * 映射字典
+ * @param {Object} response 字典数据
+ * @param {DictMeta} dictMeta 字典元数据
+ * @returns {DictData}
+ */
+function responseConverter(response, dictMeta) {
+  const dicts = response.resysDictionary.sysDictionaryDetails instanceof Array ? response.resysDictionary.sysDictionaryDetails : response
+  if (dicts === undefined) {
+    console.warn(`no dict data of "${dictMeta.type}" found in the response`)
+    return []
+  }
+  return dicts.map(d => dictConverter(d, dictMeta))
+}
+
+export function mergeOptions(src) {
+  mergeRecursive(options, src)
+}
+
+export default options

+ 33 - 0
web/src/utils/dict/index.js

@@ -0,0 +1,33 @@
+import Dict from './Dict'
+import { mergeOptions } from './DictOptions'
+
+export default function(Vue, options) {
+  mergeOptions(options)
+  Vue.mixin({
+    data() {
+      if (this.$options === undefined || this.$options.dicts === undefined || this.$options.dicts === null) {
+        return {}
+      }
+      const dict = new Dict()
+      dict.owner = this
+      return {
+        dict
+      }
+    },
+    created() {
+      if (!(this.dict instanceof Dict)) {
+        return
+      }
+      options.onCreated && options.onCreated(this.dict)
+      this.dict.init(this.$options.dicts).then(() => {
+        options.onReady && options.onReady(this.dict)
+        this.$nextTick(() => {
+          this.$emit('dictReady', this.dict)
+          if (this.$options.methods && this.$options.methods.onDictReady instanceof Function) {
+            this.$options.methods.onDictReady.call(this, this.dict)
+          }
+        })
+      })
+    },
+  })
+}

+ 87 - 87
web/src/utils/request.js

@@ -4,113 +4,113 @@ import { store } from '@/store'
 import { emitter } from '@/utils/bus.js'
 
 const service = axios.create({
-    baseURL: import.meta.env.VITE_BASE_API,
-    timeout: 99999
+  baseURL: import.meta.env.VITE_BASE_API,
+  timeout: 99999
 })
 let acitveAxios = 0
 let timer
 const showLoading = () => {
-    acitveAxios++
-    if (timer) {
-        clearTimeout(timer)
+  acitveAxios++
+  if (timer) {
+    clearTimeout(timer)
+  }
+  timer = setTimeout(() => {
+    if (acitveAxios > 0) {
+      emitter.emit('showLoading')
     }
-    timer = setTimeout(() => {
-        if (acitveAxios > 0) {
-            emitter.emit('showLoading')
-        }
-    }, 400)
+  }, 400)
 }
 
 const closeLoading = () => {
-        acitveAxios--
-        if (acitveAxios <= 0) {
-            clearTimeout(timer)
-            emitter.emit('closeLoading')
-        }
-    }
-    // http request 拦截器
+  acitveAxios--
+  if (acitveAxios <= 0) {
+    clearTimeout(timer)
+    emitter.emit('closeLoading')
+  }
+}
+// http request 拦截器
 service.interceptors.request.use(
-    config => {
-        if (!config.donNotShowLoading) {
-            showLoading()
-        }
-        const token = store.getters['user/token']
-        const user = store.getters['user/userInfo']
-        config.data = JSON.stringify(config.data)
-        config.headers = {
-            'Content-Type': 'application/json',
-            'x-token': token,
-            'x-user-id': user.ID
-        }
-        return config
-    },
-    error => {
-        closeLoading()
-        ElMessage({
-            showClose: true,
-            message: error,
-            type: 'error'
-        })
-        return error
+  config => {
+    if (!config.donNotShowLoading) {
+      showLoading()
     }
+    const token = store.getters['user/token']
+    const user = store.getters['user/userInfo']
+    config.data = JSON.stringify(config.data)
+    config.headers = {
+      'Content-Type': 'application/json',
+      'x-token': token,
+      'x-user-id': user.ID
+    }
+    return config
+  },
+  error => {
+    closeLoading()
+    ElMessage({
+      showClose: true,
+      message: error,
+      type: 'error'
+    })
+    return error
+  }
 )
 
 // http response 拦截器
 service.interceptors.response.use(
-    response => {
-        closeLoading()
-        if (response.headers['new-token']) {
-            store.commit('user/setToken', response.headers['new-token'])
-        }
-        if (response.data.code === 0 || response.headers.success === 'true') {
-            if (response.headers.msg) {
-                response.data.msg = decodeURI(response.headers.msg)
-            }
-            return response.data
-        } else {
-            ElMessage({
-                showClose: true,
-                message: response.data.msg,
-                type: 'error'
-            })
-            if (response.data.data && response.data.data.reload) {
-                store.commit('user/LoginOut')
-            }
-            return response.data.msg ? response.data : response
-        }
-    },
-    error => {
-        closeLoading()
-        switch (error.response.status) {
-            case 500:
-                ElMessageBox.confirm(`
+  response => {
+    closeLoading()
+    if (response.headers['new-token']) {
+      store.commit('user/setToken', response.headers['new-token'])
+    }
+    if (response.data.code === 0 || response.headers.success === 'true') {
+      if (response.headers.msg) {
+        response.data.msg = decodeURI(response.headers.msg)
+      }
+      return response.data
+    } else {
+      ElMessage({
+        showClose: true,
+        message: response.data.msg,
+        type: 'error'
+      })
+      if (response.data.data && response.data.data.reload) {
+        store.commit('user/LoginOut')
+      }
+      return response.data.msg ? response.data : response
+    }
+  },
+  error => {
+    closeLoading()
+    switch (error.response.status) {
+      case 500:
+        ElMessageBox.confirm(`
         <p>检测到接口错误${error}</p>
         <p>错误码<span style="color:red"> 500 </span>:此类错误内容常见于后台panic,请先查看后台日志,如果影响您正常使用可强制登出清理缓存</p>
         `, '接口报错', {
-                        dangerouslyUseHTMLString: true,
-                        distinguishCancelAndClose: true,
-                        confirmButtonText: '清理缓存',
-                        cancelButtonText: '取消'
-                    })
-                    .then(() => {
-                        store.commit('user/LoginOut')
-                    })
-                break
-            case 404:
-                ElMessageBox.confirm(`
+          dangerouslyUseHTMLString: true,
+          distinguishCancelAndClose: true,
+          confirmButtonText: '清理缓存',
+          cancelButtonText: '取消'
+        })
+          .then(() => {
+            store.commit('user/LoginOut')
+          })
+        break
+      case 404:
+        ElMessageBox.confirm(`
           <p>检测到接口错误${error}</p>
           <p>错误码<span style="color:red"> 404 </span>:此类错误多为接口未注册(或未重启)或者请求路径(方法)与api路径(方法)不符--如果为自动化代码请检查是否存在空格</p>
           `, '接口报错', {
-                    dangerouslyUseHTMLString: true,
-                    distinguishCancelAndClose: true,
-                    confirmButtonText: '我知道了',
-                    cancelButtonText: '取消'
-                })
-                break
-        }
-
-        return error
+          dangerouslyUseHTMLString: true,
+          distinguishCancelAndClose: true,
+          confirmButtonText: '我知道了',
+          cancelButtonText: '取消'
+        })
+        break
     }
+
+    return error
+  }
 )
 
-export default service
+export default service

+ 15 - 0
web/src/utils/zk.js

@@ -0,0 +1,15 @@
+// 数据合并
+export function mergeRecursive(source, target) {
+    for (var p in target) {
+        try {
+            if (target[p].constructor == Object) {
+                source[p] = mergeRecursive(source[p], target[p]);
+            } else {
+                source[p] = target[p];
+            }
+        } catch (e) {
+            source[p] = target[p];
+        }
+    }
+    return source;
+};

+ 55 - 32
web/src/view/place/place.vue

@@ -4,12 +4,17 @@
       <el-form :inline="true" :model="searchInfo" class="demo-form-inline">
         <el-form-item label="站点类型">
           <el-select v-model="searchInfo.type" clearable placeholder="请选择">
-            <el-option v-for="item in this.siteType" :label="item.label" :value="item.label"/>
+            <el-option
+              v-for="dict in dict.type.site_type"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
           </el-select>
         </el-form-item>
         <el-form-item>
           <el-button size="mini" type="primary" icon="el-icon-search" @click="onSubmit">查询</el-button>
-<!--          <el-button size="mini" type="primary" icon="el-icon-plus" @click="openDialog">新增</el-button>-->
+          <!--          <el-button size="mini" type="primary" icon="el-icon-plus" @click="openDialog">新增</el-button>-->
           <el-popover v-model:visible="deleteVisible" placement="top" width="160">
             <p>确定要删除吗?</p>
             <div style="text-align: right; margin: 0">
@@ -21,63 +26,80 @@
       </el-form>
     </div>
     <el-table
-        ref="multipleTable"
-        border
-        stripe
-        style="width: 100%"
-        tooltip-effect="dark"
-        :data="tableData"
-        @selection-change="handleSelectionChange"
+      ref="multipleTable"
+      border
+      stripe
+      style="width: 100%"
+      tooltip-effect="dark"
+      :data="tableData"
+      @selection-change="handleSelectionChange"
     >
       <!--      <el-table-column type="selection" width="55"/>-->
       <el-table-column label="创建时间" width="180">
         <template #default="scope">{{ formatDate(scope.row.CreatedAt) }}</template>
       </el-table-column>
-      <el-table-column label="站点名称" prop="name" width="180"/>
-      <el-table-column label="站点定位" prop="position" width="120">
+      <el-table-column label="站点名称" prop="name" />
+      <el-table-column label="站点定位" prop="position">
         <template #default="scope">
-          <el-link :underline="false" type="primary"
-                   @click.native="openMapHandle(scope.row.position,scope.row.name,scope.row.type)">
+          <el-link
+            :underline="false"
+            type="primary"
+            @click.native="openMapHandle(scope.row.position,scope.row.name,dict.label.site_type[scope.row.type])"
+          >
             点击查看地图
           </el-link>
         </template>
       </el-table-column>
-      <el-table-column label="站点类型" prop="type" width="150"/>
-      <el-table-column label="区域" prop="region" width="180"/>
+      <el-table-column label="站点类型" prop="type">
+        <template #default="scope">
+          <dict-tag :options="dict.type.site_type" :value="scope.row.type" />
+        </template>
+      </el-table-column>
+      <el-table-column label="区域" prop="region" />
       <el-table-column label="操作">
         <template #default="scope">
-          <el-button size="small" type="primary" icon="el-icon-edit" class="table-button"
-                     @click="updatePlace(scope.row)">变更
+          <el-button
+            size="small"
+            type="primary"
+            icon="el-icon-edit"
+            class="table-button"
+            @click="updatePlace(scope.row)"
+          >变更
           </el-button>
           <el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteRow(scope.row)">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
     <el-pagination
-        layout="total, sizes, prev, pager, next, jumper"
-        :current-page="page"
-        :page-size="pageSize"
-        :page-sizes="[10, 30, 50, 100]"
-        :style="{float:'right',padding:'20px'}"
-        :total="total"
-        @current-change="handleCurrentChange"
-        @size-change="handleSizeChange"
+      layout="total, sizes, prev, pager, next, jumper"
+      :current-page="page"
+      :page-size="pageSize"
+      :page-sizes="[10, 30, 50, 100]"
+      :style="{float:'right',padding:'20px'}"
+      :total="total"
+      @current-change="handleCurrentChange"
+      @size-change="handleSizeChange"
     />
     <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" title="弹窗操作">
       <el-form :model="formData" label-position="right" label-width="80px">
         <el-form-item label="点位名称:">
-          <el-input v-model="formData.name" clearable placeholder="请输入"/>
+          <el-input v-model="formData.name" clearable placeholder="请输入" />
         </el-form-item>
         <el-form-item label="点位定位:">
-          <el-input v-model="formData.position" :disabled="type!='create'"/>
+          <el-input v-model="formData.position" :disabled="type!='create'" />
         </el-form-item>
         <el-form-item label="点位类型:">
           <el-select v-model="formData.type">
-            <el-option v-for="item in siteType" :label="item.label" :value="item.label" :key="item.value"></el-option>
+            <el-option
+              v-for="dict in dict.type.site_type"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
           </el-select>
         </el-form-item>
         <el-form-item label="区域:">
-          <el-input v-model="formData.region" clearable placeholder="请输入"/>
+          <el-input v-model="formData.region" clearable placeholder="请输入" />
         </el-form-item>
       </el-form>
       <template #footer>
@@ -104,6 +126,7 @@ import { getDict } from '@/utils/dictionary'
 
 export default {
   name: 'Place',
+  dicts: ['site_type'],
   mixins: [infoList],
   data() {
     return {
@@ -160,7 +183,7 @@ export default {
       this.multipleSelection.map(item => {
         ids.push(item.ID)
       })
-      const res = await deletePlaceByIds({ids})
+      const res = await deletePlaceByIds({ ids })
       if (res.code === 0) {
         this.$message({
           type: 'success',
@@ -174,7 +197,7 @@ export default {
       }
     },
     async updatePlace(row) {
-      const res = await findPlace({ID: row.ID})
+      const res = await findPlace({ ID: row.ID })
       this.type = 'update'
       if (res.code === 0) {
         this.formData = res.data.replace
@@ -191,7 +214,7 @@ export default {
       }
     },
     async deletePlace(row) {
-      const res = await deletePlace({ID: row.ID})
+      const res = await deletePlace({ ID: row.ID })
       if (res.code === 0) {
         this.$message({
           type: 'success',

+ 27 - 21
web/src/view/problemInfo/proInfo.vue

@@ -1,27 +1,29 @@
 <template>
-  <div class="show" id="print"  ref="print" style="width: 100%">
+  <div id="print" ref="print" class="show" style="width: 100%">
     <div class="no-print" style="text-align: center">
       <el-button class="no-print" type="small" style="float: bottom" icon="el-icon-download" size="mini" @click="printBtn">打印保存页面</el-button>
     </div>
-    <el-form :model="formData" label-position="right" label-width="80px" >
+    <el-form :model="formData" label-position="right" label-width="80px">
       <el-card class="box-card">
         <el-descriptions title="基本信息" border :column="2">
           <el-descriptions-item label="发布人">{{ formData.oper }}</el-descriptions-item>
           <el-descriptions-item label="站点名称">{{ formData.siteName }}</el-descriptions-item>
           <el-descriptions-item label="站点位置">{{ formData.position }}</el-descriptions-item>
-          <el-descriptions-item label="站点类型">{{ formData.siteType }}</el-descriptions-item>
+          <el-descriptions-item label="站点类型"><dict-tag :options="dict.type.site_type" :value="formData.siteType" /></el-descriptions-item>
           <el-descriptions-item label="处理状态">
             <el-tag v-show="formData.status == 'Untreated'" type="warning">未处理</el-tag>
             <el-tag v-show="formData.status == 'Processed'" type="success">已处理</el-tag>
           </el-descriptions-item>
           <el-descriptions-item label="责任部门">{{ formData.department }}</el-descriptions-item>
+          <el-descriptions-item label="一类单位">{{ formData.unitName }}</el-descriptions-item>
+          <el-descriptions-item label="扣评分">{{ formData.integral/10 }}</el-descriptions-item>
           <el-descriptions-item span="2" label="问题备注">{{ formData.remark }}</el-descriptions-item>
         </el-descriptions>
       </el-card>
       <el-card class="box-card">
         <el-descriptions title="问题列表" :column="1" direction="vertical">
           <el-descriptions-item v-for="item in formData.matter.split('|')">
-            {{ matterList[item] != undefined ? matterList[item].label : '' }}
+            {{ matterList[item] != undefined ? matterList[item] : '' }}
           </el-descriptions-item>
         </el-descriptions>
       </el-card>
@@ -30,20 +32,20 @@
           <el-descriptions-item class="img" label="问题图片">
             <span v-show="formData.imgList.length<1">无图片</span>
             <img
-                v-for="img in formData.imgList"
-                style="width: 30%; height: 240px;padding-left: 1%"
-                :src="img"
-            />
+              v-for="img in formData.imgList"
+              style="width: 30%; height: 240px;padding-left: 1%"
+              :src="img"
+            >
           </el-descriptions-item>
           <el-descriptions-item label="问题视频">
             <span v-show="formData.video.length<1">无视频</span>
             <video
-                v-show="formData.video.length>0"
-                style="object-fit:fill"
-                controls
-                width="400"
-                height="240"
-                :src="formData.video"
+              v-show="formData.video.length>0"
+              style="object-fit:fill"
+              controls
+              width="400"
+              height="240"
+              :src="formData.video"
             >
               您的浏览器不支持Video标签。
             </video>
@@ -54,12 +56,12 @@
         <el-descriptions title="处理结果" :column="1" border direction="vertical">
           <el-descriptions-item label="处理人">{{ formData.handler }}</el-descriptions-item>
           <el-descriptions-item label="处理内容">{{ formData.handText }}</el-descriptions-item>
-          <el-descriptions-item label="处理图片" class="img" >
+          <el-descriptions-item label="处理图片" class="img">
             <img
-                v-for="img in formData.handImgList"
-                style="width: 30%; height: 240px;padding-left: 1%"
-                :src="img"
-            />
+              v-for="img in formData.handImgList"
+              style="width: 30%; height: 240px;padding-left: 1%"
+              :src="img"
+            >
           </el-descriptions-item>
         </el-descriptions>
       </el-card>
@@ -72,6 +74,7 @@ import { findProblemInfo } from '@/api/problemInfo'
 import Print from '@/utils/print'
 export default {
   name: 'ProInfo',
+  dicts: ['site_type'],
   data() {
     return {
       matterList: [],
@@ -95,7 +98,7 @@ export default {
     }
   },
   async created() {
-    const res = await findProblemInfo({ID: this.$route.query.Id})
+    const res = await findProblemInfo({ ID: this.$route.query.Id })
     if (res.code === 0) {
       this.formData = res.data.reproblemInfo
       if (this.formData.imgs.length > 0) {
@@ -108,7 +111,10 @@ export default {
       } else {
         this.formData.handImgList = []
       }
-      this.matterList = res.data.reproblemInfo.matterList.sysDictionaryDetails
+      const temp = res.data.reproblemInfo.matterList
+      for (const index in temp) {
+        this.matterList[temp[index].ID] = temp[index].problem
+      }
       this.dialogFormVisible = true
     }
   },

+ 90 - 72
web/src/view/problemInfo/problemInfo.vue

@@ -4,13 +4,18 @@
       <el-form :inline="true" :model="searchInfo" class="demo-form-inline">
         <el-form-item label="站点类型">
           <el-select v-model="searchInfo.siteType" clearable placeholder="请选择">
-            <el-option v-for="item in siteType" :label="item.label" :value="item.value"/>
+            <el-option
+              v-for="dict in dict.type.site_type"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
           </el-select>
         </el-form-item>
         <el-form-item label="处理状态">
           <el-select v-model="searchInfo.status" clearable placeholder="请选择">
-            <el-option label="已处理" value="Processed"/>
-            <el-option label="未处理" value="Untreated"/>
+            <el-option label="已处理" value="Processed" />
+            <el-option label="未处理" value="Untreated" />
           </el-select>
         </el-form-item>
         <el-form-item>
@@ -29,37 +34,43 @@
       </el-form>
     </div>
     <el-table
-        ref="multipleTable"
-        border
-        stripe
-        style="width: 100%"
-        tooltip-effect="dark"
-        :data="tableData"
-        @selection-change="handleSelectionChange"
+      ref="multipleTable"
+      border
+      stripe
+      style="width: 100%"
+      tooltip-effect="dark"
+      :data="tableData"
+      @selection-change="handleSelectionChange"
     >
       <el-table-column label="日期" width="180">
         <template #default="scope">{{ formatDate(scope.row.CreatedAt) }}</template>
       </el-table-column>
-      <el-table-column label="发布人" prop="oper" width="120"/>
-      <el-table-column label="站点" prop="siteName" width="220"/>
-      <el-table-column label="站点类型" prop="siteType" width="120"/>
-      <el-table-column label="已登录查阅次数" prop="count" width="120"/>
-      <el-table-column label="一类单位" prop="unitName" width="120"/>
-      <el-table-column label="分数" prop="integral" width="120"/>
-      <el-table-column label="处理状态" prop="status" width="120">
+      <el-table-column label="发布人" prop="oper" />
+      <el-table-column label="站点" prop="siteName" />
+      <el-table-column label="站点类型" prop="siteType">
+        <template #default="scope">
+          <dict-tag :options="dict.type.site_type" :value="scope.row.siteType" />
+        </template>
+      </el-table-column>
+      <el-table-column label="已登录查阅次数" prop="count" />
+      <el-table-column label="一类单位" prop="unitName" />
+      <el-table-column label="扣评分" prop="integral">
+        <template #default="scope">{{ scope.row.integral/10 }}</template>
+      </el-table-column>
+      <el-table-column label="处理状态" prop="status">
         <template #default="scope">
           <el-tag v-show="scope.row.status == 'Untreated'" type="warning">未处理</el-tag>
           <el-tag v-show="scope.row.status == 'Processed'" type="success">已处理</el-tag>
         </template>
       </el-table-column>
-      <el-table-column label="责任部门" prop="department" width="120"/>
-      <el-table-column label="操作">
+      <el-table-column label="责任部门" prop="department" />
+      <el-table-column label="操作" width="300">
         <template #default="scope">
           <el-button
-              size="small"
-              type="primary"
-              class="table-button"
-              @click="updateProblemInfo(scope.row)"
+            size="small"
+            type="primary"
+            class="table-button"
+            @click="updateProblemInfo(scope.row)"
           >查看详情
           </el-button>
           <el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteRow(scope.row)">删除</el-button>
@@ -70,33 +81,33 @@
       </el-table-column>
     </el-table>
     <el-pagination
-        layout="total, sizes, prev, pager, next, jumper"
-        :current-page="page"
-        :page-size="pageSize"
-        :page-sizes="[10, 30, 50, 100]"
-        :style="{float:'right',padding:'20px'}"
-        :total="total"
-        @current-change="handleCurrentChange"
-        @size-change="handleSizeChange"
+      layout="total, sizes, prev, pager, next, jumper"
+      :current-page="page"
+      :page-size="pageSize"
+      :page-sizes="[10, 30, 50, 100]"
+      :style="{float:'right',padding:'20px'}"
+      :total="total"
+      @current-change="handleCurrentChange"
+      @size-change="handleSizeChange"
     />
-    <el-dialog title="选择通知人" v-model="noticeList" width="500px" append-to-body>
+    <el-dialog v-model="noticeList" title="选择通知人" width="500px" append-to-body>
       <el-form v-model="noticeUser" label-width="120px">
         <el-row>
           <el-col :span="24">
             <el-form-item label="选择通知人" :rules="{required: true, message: '请选择通知人'}">
               <el-select
-                  v-model="noticeUser.userList"
-                  filterable
-                  clearable
-                  multiple
-                  size="small"
-                  style="width: 240px"
+                v-model="noticeUser.userList"
+                filterable
+                clearable
+                multiple
+                size="small"
+                style="width: 240px"
               >
                 <el-option
-                    v-for="id in Object.keys(userIds)"
-                    :key="id"
-                    :label="userIds[id]"
-                    :value="id"
+                  v-for="id in Object.keys(userIds)"
+                  :key="id"
+                  :label="userIds[id]"
+                  :value="id"
                 />
               </el-select>
             </el-form-item>
@@ -109,9 +120,10 @@
       </div>
     </el-dialog>
     <el-dialog
-        title="已阅详情"
-        v-model="dialogVisibleRead"
-        width="30%">
+      v-model="dialogVisibleRead"
+      title="已阅详情"
+      width="30%"
+    >
       <div style="text-align: center;padding-bottom: 20px">
         <span>{{ readMsg }}</span>
       </div>
@@ -119,26 +131,28 @@
         <el-button type="primary" @click="closeRead">确 定</el-button>
       </div>
     </el-dialog>
-    <el-dialog ref="problemInfo" v-model="dialogFormVisible" id="problemInfo" :before-close="closeDialog" title="问题详情">
+    <el-dialog id="problemInfo" ref="problemInfo" v-model="dialogFormVisible" :before-close="closeDialog" title="问题详情">
       <el-form :model="formData" label-position="right" label-width="80px">
         <el-card class="box-card">
           <el-descriptions title="基本信息" border :column="2">
             <el-descriptions-item label="发布人">{{ formData.oper }}</el-descriptions-item>
             <el-descriptions-item label="站点名称">{{ formData.siteName }}</el-descriptions-item>
             <el-descriptions-item label="站点位置">{{ formData.position }}</el-descriptions-item>
-            <el-descriptions-item label="站点类型">{{ formData.siteType }}</el-descriptions-item>
+            <el-descriptions-item label="站点类型"><dict-tag :options="dict.type.site_type" :value="formData.siteType " /></el-descriptions-item>
             <el-descriptions-item label="处理状态">
               <el-tag v-show="formData.status == 'Untreated'" type="warning">未处理</el-tag>
               <el-tag v-show="formData.status == 'Processed'" type="success">已处理</el-tag>
             </el-descriptions-item>
             <el-descriptions-item label="责任部门">{{ formData.department }}</el-descriptions-item>
+            <el-descriptions-item label="一类单位">{{ formData.unitName }}</el-descriptions-item>
+            <el-descriptions-item label="扣评分">{{ formData.integral/10 }}</el-descriptions-item>
             <el-descriptions-item span="2" label="问题备注">{{ formData.remark }}</el-descriptions-item>
           </el-descriptions>
         </el-card>
         <el-card class="box-card">
           <el-descriptions title="问题列表" :column="1" direction="vertical">
             <el-descriptions-item v-for="item in formData.matter.split('|')">
-              {{ matterList[item] != undefined ? matterList[item].label : '' }}
+              {{ matterList[item] != undefined ? matterList[item] : '' }}
             </el-descriptions-item>
           </el-descriptions>
         </el-card>
@@ -146,20 +160,20 @@
           <el-descriptions title="问题图片/视频" direction="vertical">
             <el-descriptions-item label="问题图片(点击图片查看更多)">
               <el-image
-                  style="width: 260px; height: 240px"
-                  :src="(formData.imgList.length>0?formData.imgList[0]:'')"
-                  :preview-src-list="formData.imgList"
+                style="width: 260px; height: 240px"
+                :src="(formData.imgList.length>0?formData.imgList[0]:'')"
+                :preview-src-list="formData.imgList"
               />
             </el-descriptions-item>
             <el-descriptions-item label="问题视频">
               <span v-show="formData.video.length<1">无视频</span>
               <video
-                  v-show="formData.video.length>0"
-                  style="object-fit:fill"
-                  controls
-                  width="400"
-                  height="240"
-                  :src="formData.video"
+                v-show="formData.video.length>0"
+                style="object-fit:fill"
+                controls
+                width="400"
+                height="240"
+                :src="formData.video"
               >
                 您的浏览器不支持Video标签。
               </video>
@@ -172,9 +186,9 @@
             <el-descriptions-item label="处理内容">{{ formData.handText }}</el-descriptions-item>
             <el-descriptions-item label="处理图片(点击图片查看更多)">
               <el-image
-                  style="width: 260px; height: 240px"
-                  :src="(formData.handImgList.length>0?formData.handImgList[0]:'')"
-                  :preview-src-list="formData.handImgList"
+                style="width: 260px; height: 240px"
+                :src="(formData.handImgList.length>0?formData.handImgList[0]:'')"
+                :preview-src-list="formData.handImgList"
               />
             </el-descriptions-item>
           </el-descriptions>
@@ -195,12 +209,13 @@ import {
   exportExcel, sendUserProblemInfo, getReadCountList
 } from '@/api/problemInfo' //  此处请自行替换地址
 import infoList from '@/mixins/infoList'
-import {getDict} from '@/utils/dictionary'
-import {getUserPList} from "@/api/user";
+import { getDict } from '@/utils/dictionary'
+import { getUserPList } from '@/api/user'
 
 export default {
   name: 'ProblemInfo',
   mixins: [infoList],
+  dicts: ['site_type'],
   data() {
     return {
       listApi: getProblemInfoList,
@@ -271,14 +286,14 @@ export default {
     async openUser(row) {
       this.sendId = row.ID
       this.noticeList = true
-      getUserPList({page: 1, pageSize: 9999}).then(res => {
+      getUserPList({ page: 1, pageSize: 9999 }).then(res => {
         for (const user in res.data.list) {
           this.userIds[res.data.list[user].ID] = res.data.list[user].userName
         }
       })
     },
     sendUser() {
-      sendUserProblemInfo({ID: this.noticeUser.userList, ProblemID: this.sendId}).then(res => {
+      sendUserProblemInfo({ ID: this.noticeUser.userList, ProblemID: this.sendId }).then(res => {
         console.log(res)
         this.closeSend()
       })
@@ -290,16 +305,16 @@ export default {
       this.sendId = 0
     },
     showReadInfo(row) {
-      getReadCountList({page: 1, pageSize: 9999, problemId: row.ID}).then(res => {
-        this.dialogVisibleRead = true;
+      getReadCountList({ page: 1, pageSize: 9999, problemId: row.ID }).then(res => {
+        this.dialogVisibleRead = true
         this.readMsg = ''
         for (const read in res.data.list) {
-          this.readMsg=this.readMsg.concat(res.data.list[read].userName + ':' + res.data.list[read].count + '次、')
+          this.readMsg = this.readMsg.concat(res.data.list[read].userName + ':' + res.data.list[read].count + '次、')
         }
       })
     },
     closeRead() {
-      this.dialogVisibleRead = false;
+      this.dialogVisibleRead = false
       this.readMsg = ''
     },
     async onDelete() {
@@ -315,7 +330,7 @@ export default {
       this.multipleSelection.map(item => {
         ids.push(item.ID)
       })
-      const res = await deleteProblemInfoByIds({ids})
+      const res = await deleteProblemInfoByIds({ ids })
       if (res.code === 0) {
         this.$message({
           type: 'success',
@@ -329,7 +344,7 @@ export default {
       }
     },
     async updateProblemInfo(row) {
-      const res = await findProblemInfo({ID: row.ID})
+      const res = await findProblemInfo({ ID: row.ID })
       this.type = 'update'
       if (res.code === 0) {
         this.formData = res.data.reproblemInfo
@@ -343,7 +358,10 @@ export default {
         } else {
           this.formData.handImgList = []
         }
-        this.matterList = res.data.reproblemInfo.matterList.sysDictionaryDetails
+        const temp = res.data.reproblemInfo.matterList
+        for (const index in temp) {
+          this.matterList[temp[index].ID] = temp[index].problem
+        }
         this.dialogFormVisible = true
       }
     },
@@ -372,7 +390,7 @@ export default {
       }
     },
     async deleteProblemInfo(row) {
-      const res = await deleteProblemInfo({ID: row.ID})
+      const res = await deleteProblemInfo({ ID: row.ID })
       if (res.code === 0) {
         this.$message({
           type: 'success',

+ 243 - 0
web/src/view/problemType/problemType.vue

@@ -0,0 +1,243 @@
+<template>
+  <div>
+    <div class="search-term">
+      <el-form :inline="true" :model="searchInfo" class="demo-form-inline">
+        <el-form-item label="站点类型">
+          <el-select v-model="searchInfo.siteType" clearable placeholder="请选择">
+            <el-option
+              v-for="dict in dict.type.site_type"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button size="mini" type="primary" icon="el-icon-search" @click="onSubmit">查询</el-button>
+          <el-button size="mini" type="primary" icon="el-icon-plus" @click="openDialog">新增</el-button>
+          <el-popover v-model:visible="deleteVisible" placement="top" width="160">
+            <p>确定要删除吗?</p>
+            <div style="text-align: right; margin: 0">
+              <el-button size="mini" type="text" @click="deleteVisible = false">取消</el-button>
+              <el-button size="mini" type="primary" @click="onDelete">确定</el-button>
+            </div>
+            <template #reference>
+              <el-button icon="el-icon-delete" size="mini" type="danger" style="margin-left: 10px;">批量删除</el-button>
+            </template>
+          </el-popover>
+        </el-form-item>
+      </el-form>
+    </div>
+    <el-table
+      ref="multipleTable"
+      border
+      stripe
+      style="width: 100%"
+      tooltip-effect="dark"
+      :data="tableData"
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column type="selection" width="55" />
+      <el-table-column label="日期" width="180">
+        <template #default="scope">{{ formatDate(scope.row.CreatedAt) }}</template>
+      </el-table-column>
+      <el-table-column label="站点类型" prop="siteType">
+        <template #default="scope">
+          <dict-tag :options="dict.type.site_type" :value="scope.row.siteType" />
+        </template>
+      </el-table-column>
+      <el-table-column label="问题" prop="problem" />
+      <el-table-column label="分数" prop="integral">
+        <template #default="scope">
+          {{ scope.row.integral/10 }}
+        </template>
+      </el-table-column>
+      <el-table-column label="按钮组">
+        <template #default="scope">
+          <!--          <el-button size="small" type="primary" icon="el-icon-edit" class="table-button" @click="updateProblemType(scope.row)">变更</el-button>-->
+          <el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteRow(scope.row)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <el-pagination
+      layout="total, sizes, prev, pager, next, jumper"
+      :current-page="page"
+      :page-size="pageSize"
+      :page-sizes="[10, 30, 50, 100]"
+      :style="{float:'right',padding:'20px'}"
+      :total="total"
+      @current-change="handleCurrentChange"
+      @size-change="handleSizeChange"
+    />
+    <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" title="弹窗操作">
+      <el-form :model="formData" label-position="right" label-width="80px">
+        <el-form-item label="站点类型:">
+          <el-select
+            v-model="formData.siteType"
+            placeholder="请选择站点类型"
+            clearable
+            size="small"
+            style="width: 240px"
+          >
+            <el-option
+              v-for="dict in dict.type.site_type"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="问题:">
+          <el-input v-model="formData.problem" clearable placeholder="请输入" />
+        </el-form-item>
+        <el-form-item label="分数:">
+          <el-input v-model.number="formData.integral" clearable placeholder="请输入" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="closeDialog">取 消</el-button>
+          <el-button type="primary" @click="enterDialog">确 定</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  createProblemType,
+  deleteProblemType,
+  deleteProblemTypeByIds,
+  updateProblemType,
+  findProblemType,
+  getProblemTypeList
+} from '@/api/problemType' //  此处请自行替换地址
+import infoList from '@/mixins/infoList'
+export default {
+  name: 'ProblemType',
+  dicts: ['site_type'],
+  mixins: [infoList],
+  data() {
+    return {
+      listApi: getProblemTypeList,
+      dialogFormVisible: false,
+      type: '',
+      deleteVisible: false,
+      multipleSelection: [],
+      formData: {
+        siteType: null,
+        problem: '',
+        integral: 0,
+      }
+    }
+  },
+  async created() {
+    await this.getTableData()
+  },
+  methods: {
+  // 条件搜索前端看此方法
+    onSubmit() {
+      this.page = 1
+      this.pageSize = 10
+      this.getTableData()
+    },
+    handleSelectionChange(val) {
+      this.multipleSelection = val
+    },
+    deleteRow(row) {
+      this.$confirm('确定要删除吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.deleteProblemType(row)
+      })
+    },
+    async onDelete() {
+      const ids = []
+      if (this.multipleSelection.length === 0) {
+        this.$message({
+          type: 'warning',
+          message: '请选择要删除的数据'
+        })
+        return
+      }
+      this.multipleSelection &&
+        this.multipleSelection.map(item => {
+          ids.push(item.ID)
+        })
+      const res = await deleteProblemTypeByIds({ ids })
+      if (res.code === 0) {
+        this.$message({
+          type: 'success',
+          message: '删除成功'
+        })
+        if (this.tableData.length === ids.length && this.page > 1) {
+          this.page--
+        }
+        this.deleteVisible = false
+        this.getTableData()
+      }
+    },
+    async updateProblemType(row) {
+      const res = await findProblemType({ ID: row.ID })
+      this.type = 'update'
+      if (res.code === 0) {
+        this.formData = res.data.reproblemType
+        this.dialogFormVisible = true
+      }
+    },
+    closeDialog() {
+      this.dialogFormVisible = false
+      this.formData = {
+        siteType: 0,
+        problem: '',
+        integral: 0,
+      }
+    },
+    async deleteProblemType(row) {
+      const res = await deleteProblemType({ ID: row.ID })
+      if (res.code === 0) {
+        this.$message({
+          type: 'success',
+          message: '删除成功'
+        })
+        if (this.tableData.length === 1 && this.page > 1) {
+          this.page--
+        }
+        this.getTableData()
+      }
+    },
+    async enterDialog() {
+      let res
+      switch (this.type) {
+        case 'create':
+          res = await createProblemType(this.formData)
+          break
+        case 'update':
+          res = await updateProblemType(this.formData)
+          break
+        default:
+          res = await createProblemType(this.formData)
+          break
+      }
+      if (res.code === 0) {
+        this.$message({
+          type: 'success',
+          message: '创建/更改成功'
+        })
+        this.closeDialog()
+        this.getTableData()
+      }
+    },
+    openDialog() {
+      this.type = 'create'
+      this.dialogFormVisible = true
+    }
+  },
+}
+</script>
+
+<style>
+</style>

+ 82 - 0
web/src/view/problemType/problemTypeForm.vue

@@ -0,0 +1,82 @@
+<template>
+  <div>
+    <el-form :model="formData" label-position="right" label-width="80px">
+      <el-form-item label="站点类型:">
+        <el-input v-model.number="formData.siteType" clearable placeholder="请输入" />
+      </el-form-item>
+      <el-form-item label="问题:">
+        <el-input v-model="formData.problem" clearable placeholder="请输入" />
+      </el-form-item>
+      <el-form-item label="分数:">
+        <el-input v-model.number="formData.integral" clearable placeholder="请输入" />
+      </el-form-item>
+      <el-form-item>
+        <el-button size="mini" type="primary" @click="save">保存</el-button>
+        <el-button size="mini" type="primary" @click="back">返回</el-button>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import {
+  createProblemType,
+  updateProblemType,
+  findProblemType
+} from '@/api/problemType' //  此处请自行替换地址
+import infoList from '@/mixins/infoList'
+export default {
+  name: 'ProblemType',
+  mixins: [infoList],
+  data() {
+    return {
+      type: '',
+      formData: {
+        siteType: 0,
+        problem: '',
+        integral: 0,
+      }
+    }
+  },
+  async created() {
+    // 建议通过url传参获取目标数据ID 调用 find方法进行查询数据操作 从而决定本页面是create还是update 以下为id作为url参数示例
+    if (this.$route.query.id) {
+      const res = await findProblemType({ ID: this.$route.query.id })
+      if (res.code === 0) {
+        this.formData = res.data.reproblemType
+        this.type = 'update'
+      }
+    } else {
+      this.type = 'create'
+    }
+  },
+  methods: {
+    async save() {
+      let res
+      switch (this.type) {
+        case 'create':
+          res = await createProblemType(this.formData)
+          break
+        case 'update':
+          res = await updateProblemType(this.formData)
+          break
+        default:
+          res = await createProblemType(this.formData)
+          break
+      }
+      if (res.code === 0) {
+        this.$message({
+          type: 'success',
+          message: '创建/更改成功'
+        })
+      }
+    },
+    back() {
+      this.$router.go(-1)
+    }
+  }
+}
+</script>
+
+<style>
+</style>

+ 123 - 21
web/src/view/unit/unit.vue

@@ -2,18 +2,22 @@
   <div>
     <div class="search-term">
       <el-form :inline="true" :model="searchInfo" class="demo-form-inline">
+        <el-form-item label="单位名称">
+          <el-input v-model="searchInfo.unitName" clearable placeholder="请输入单位名称" />
+        </el-form-item>
         <el-form-item>
           <el-button size="mini" type="primary" icon="el-icon-search" @click="onSubmit">查询</el-button>
-          <el-button size="mini" type="primary" icon="el-icon-plus" @click="openDialog">新增</el-button>
+          <el-button size="mini" type="primary" icon="el-icon-plus" @click="openDialog">新增一类单位</el-button>
+          <el-button size="mini" type="primary" icon="el-icon-plus" @click="updateUnit">重新开始下期</el-button>
           <el-popover v-model:visible="deleteVisible" placement="top" width="160">
             <p>确定要删除吗?</p>
             <div style="text-align: right; margin: 0">
               <el-button size="mini" type="text" @click="deleteVisible = false">取消</el-button>
               <el-button size="mini" type="primary" @click="onDelete">确定</el-button>
             </div>
-            <template #reference>
-              <el-button icon="el-icon-delete" size="mini" type="danger" style="margin-left: 10px;">批量删除</el-button>
-            </template>
+            <!--            <template #reference>-->
+            <!--              <el-button icon="el-icon-delete" size="mini" type="danger" style="margin-left: 10px;">批量删除</el-button>-->
+            <!--            </template>-->
           </el-popover>
         </el-form-item>
       </el-form>
@@ -27,15 +31,23 @@
       :data="tableData"
       @selection-change="handleSelectionChange"
     >
-      <el-table-column type="selection" width="55" />
-      <el-table-column label="日期" width="180">
-        <template #default="scope">{{ formatDate(scope.row.CreatedAt) }}</template>
+      <!--      <el-table-column type="selection" width="55" />-->
+      <!--      <el-table-column label="日期" width="180">-->
+      <!--        <template #default="scope">{{ formatDate(scope.row.CreatedAt) }}</template>-->
+      <!--      </el-table-column>-->
+      <el-table-column label="单位名称" prop="unitName" />
+      <el-table-column label="满分" prop="unitIntegral">
+        <template #default="scope">{{ scope.row.unitMaxIntegral/10 }}</template>
+      </el-table-column>
+      <el-table-column label="扣分" prop="unitIntegral">
+        <template #default="scope">{{ (scope.row.unitMaxIntegral-scope.row.unitIntegral)/10 }}</template>
+      </el-table-column>
+      <el-table-column label="得分" prop="unitIntegral">
+        <template #default="scope">{{ scope.row.unitIntegral/10 }}</template>
       </el-table-column>
-      <el-table-column label="单位名称" prop="unitName" width="120" />
-      <el-table-column label="现有积分" prop="unitIntegral" width="120" />
       <el-table-column label="按钮组">
         <template #default="scope">
-          <el-button size="small" type="primary" icon="el-icon-edit" class="table-button" @click="updateUnit(scope.row)">变更</el-button>
+          <el-button size="small" type="primary" icon="el-icon-edit" @click="openProDialog(scope.row)">详情</el-button>
           <el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteRow(scope.row)">删除</el-button>
         </template>
       </el-table-column>
@@ -50,13 +62,14 @@
       @current-change="handleCurrentChange"
       @size-change="handleSizeChange"
     />
+
     <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" title="弹窗操作">
       <el-form :model="formData" label-position="right" label-width="80px">
-        <el-form-item label="单位名称:">
+        <el-form-item v-show="type=='create'" label="单位名称:">
           <el-input v-model="formData.unitName" clearable placeholder="请输入" />
         </el-form-item>
-        <el-form-item label="现有积分:">
-          <el-input v-model.number="formData.unitIntegral" clearable placeholder="请输入" />
+        <el-form-item v-show="type=='update'" label="开始积分:">
+          <el-input v-model.number="formData.unitIntegral" clearable placeholder="请输入开始积分" />
         </el-form-item>
       </el-form>
       <template #footer>
@@ -66,6 +79,52 @@
         </div>
       </template>
     </el-dialog>
+
+    <el-dialog v-model="dialogFormVisiblePro" :before-close="closeDialogPro" title="扣分详情">
+      <div>
+        <el-pagination
+          layout="total, sizes, prev, pager, next, jumper"
+          :current-page="pagePro"
+          :page-size="pageSizePro"
+          :page-sizes="[10, 30, 50, 100]"
+          :style="{float:'right',padding:'20px'}"
+          :total="totalPro"
+          @current-change="handleCurrentChangePro"
+          @size-change="handleSizeChangePro"
+        />
+        <el-table
+          ref="crudItem"
+          border
+          stripe
+          style="width: 100%"
+          tooltip-effect="dark"
+          :data="tableDataPro"
+        >
+          <el-table-column label="日期" width="180">
+            <template #default="scope">{{ formatDate(scope.row.CreatedAt) }}</template>
+          </el-table-column>
+          <el-table-column label="发布人" prop="oper" />
+          <el-table-column label="站点" prop="siteName" />
+          <el-table-column label="站点类型" prop="siteType">
+            <template #default="scope">
+              <dict-tag :options="dict.type.site_type" :value="scope.row.siteType" />
+            </template>
+          </el-table-column>
+          <el-table-column label="已登录查阅次数" prop="count" />
+          <el-table-column label="一类单位" prop="unitName" />
+          <el-table-column label="扣评分" prop="integral">
+            <template #default="scope">{{ scope.row.integral/10 }}</template>
+          </el-table-column>
+          <el-table-column label="处理状态" prop="status">
+            <template #default="scope">
+              <el-tag v-show="scope.row.status == 'Untreated'" type="warning">未处理</el-tag>
+              <el-tag v-show="scope.row.status == 'Processed'" type="success">已处理</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column label="责任部门" prop="department" />
+        </el-table>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
@@ -75,23 +134,34 @@ import {
   deleteUnit,
   deleteUnitByIds,
   updateUnit,
-  findUnit,
   getUnitList
 } from '@/api/unit' //  此处请自行替换地址
 import infoList from '@/mixins/infoList'
+import { getProblemInfoList } from '@/api/problemInfo'
 export default {
   name: 'Unit',
+  dicts: ['site_type'],
   mixins: [infoList],
   data() {
     return {
       listApi: getUnitList,
+      listProApi: getProblemInfoList,
       dialogFormVisible: false,
       type: '',
       deleteVisible: false,
       multipleSelection: [],
+      dialogFormVisiblePro: false,
+      tableDataPro: [],
+      pagePro: 1,
+      totalPro: 10,
+      pageSizePro: 10,
+      searchInfoPro: {
+        CreatedAtStart: new Date(),
+        CreatedAtEnd: new Date()
+      },
       formData: {
         unitName: '',
-        unitIntegral: 0,
+        unitIntegral: 100,
       }
     }
   },
@@ -144,18 +214,15 @@ export default {
       }
     },
     async updateUnit(row) {
-      const res = await findUnit({ ID: row.ID })
+      // const res = await findUnit({ ID: row.ID })
       this.type = 'update'
-      if (res.code === 0) {
-        this.formData = res.data.reunit
-        this.dialogFormVisible = true
-      }
+      this.dialogFormVisible = true
     },
     closeDialog() {
       this.dialogFormVisible = false
       this.formData = {
         unitName: '',
-        unitIntegral: 0,
+        unitIntegral: 100,
       }
     },
     async deleteUnit(row) {
@@ -196,6 +263,41 @@ export default {
     openDialog() {
       this.type = 'create'
       this.dialogFormVisible = true
+    },
+    openProDialog(row) {
+      this.dialogFormVisiblePro = true
+      const formatDateStr = row.period.replace(/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/, '$1/$2/$3 $4:$5:$6')
+      // 将时间格式化成 yyyy-MM-dd HH:mm:ss
+      this.searchInfoPro.CreatedAtStart = new Date(formatDateStr)
+      this.searchInfoPro.CreatedAtEnd = new Date()
+      this.searchInfoPro.unitId = row.ID
+      this.getTableDataPro()
+    },
+    handleSizeChangePro(val) {
+      this.pageSizePro = val
+      this.getTableDataPro()
+    },
+    handleCurrentChangePro(val) {
+      this.pagePro = val
+      this.getTableDataPro()
+    },
+    closeDialogPro() {
+      this.dialogFormVisiblePro = false
+      this.formData = {
+        unitName: '',
+        unitIntegral: 0,
+      }
+    },
+    getTableDataPro(page = this.pagePro, pageSize = this.pageSizePro) {
+      this.listProApi({ page, pageSize, ...this.searchInfoPro }).then(res => {
+        console.log(res)
+        if (res.code === 0) {
+          this.tableDataPro = res.data.list
+          this.totalPro = res.data.total
+          this.pagePro = res.data.page
+          this.pageSizePro = res.data.pageSize
+        }
+      })
     }
   },
 }

+ 336 - 0
web/src/view/unitHistory/unitHistory.vue

@@ -0,0 +1,336 @@
+<template>
+  <div>
+    <div class="search-term">
+      <el-form :inline="true" :model="searchInfo" class="demo-form-inline">
+        <el-form-item label="单位名称">
+          <el-input v-model="searchInfo.unitName" clearable placeholder="请输入单位名称" />
+        </el-form-item>
+        <el-form-item label="期编号">
+          <el-input v-model="searchInfo.period" clearable placeholder="请输入期编号" />
+        </el-form-item>
+        <el-form-item>
+          <el-button size="mini" type="primary" icon="el-icon-search" @click="onSubmit">查询</el-button>
+          <el-popover v-model:visible="deleteVisible" placement="top" width="160">
+            <p>确定要删除吗?</p>
+            <div style="text-align: right; margin: 0">
+              <el-button size="mini" type="text" @click="deleteVisible = false">取消</el-button>
+              <el-button size="mini" type="primary" @click="onDelete">确定</el-button>
+            </div>
+            <!--            <template #reference>-->
+            <!--              <el-button icon="el-icon-delete" size="mini" type="danger" style="margin-left: 10px;">批量删除</el-button>-->
+            <!--            </template>-->
+          </el-popover>
+        </el-form-item>
+      </el-form>
+    </div>
+    <el-table
+      ref="multipleTable"
+      border
+      stripe
+      style="width: 100%"
+      tooltip-effect="dark"
+      :data="tableData"
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column type="selection" width="55" />
+      <el-table-column label="期开始时间" width="180">
+        <template #default="scope">{{ formatDate(scope.row.CreatedAt) }}</template>
+      </el-table-column>
+      <el-table-column label="期编号" prop="period" />
+      <!--      <el-table-column label="单位id" prop="unitId" />-->
+      <el-table-column label="单位名称" prop="unitName" />
+      <el-table-column label="满分" prop="unitIntegral">
+        <template #default="scope">{{ scope.row.unitMaxIntegral/10 }}</template>
+      </el-table-column>
+      <el-table-column label="扣分" prop="unitIntegral">
+        <template #default="scope">{{ (scope.row.unitMaxIntegral-scope.row.unitIntegral)/10 }}</template>
+      </el-table-column>
+      <el-table-column label="得分" prop="unitIntegral">
+        <template #default="scope">{{ scope.row.unitIntegral/10 }}</template>
+      </el-table-column>
+      <!--      <el-table-column label="关联问题id" prop="problemIds" />-->
+      <el-table-column label="按钮组">
+        <template #default="scope">
+          <el-button size="small" type="primary" icon="el-icon-edit" class="table-button" @click="openProDialog(scope.row)">扣分详情</el-button>
+          <!--          <el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteRow(scope.row)">删除</el-button>-->
+        </template>
+      </el-table-column>
+    </el-table>
+    <el-pagination
+      layout="total, sizes, prev, pager, next, jumper"
+      :current-page="page"
+      :page-size="pageSize"
+      :page-sizes="[10, 30, 50, 100]"
+      :style="{float:'right',padding:'20px'}"
+      :total="total"
+      @current-change="handleCurrentChange"
+      @size-change="handleSizeChange"
+    />
+    <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" title="弹窗操作">
+      <el-form :model="formData" label-position="right" label-width="80px">
+        <el-form-item label="单位名称:">
+          <el-input v-model="formData.unitName" clearable placeholder="请输入" />
+        </el-form-item>
+        <el-form-item label="现有积分:">
+          <el-input v-model.number="formData.unitIntegral" clearable placeholder="请输入" />
+        </el-form-item>
+        <el-form-item label="满分:">
+          <el-input v-model.number="formData.unitMaxIntegral" clearable placeholder="请输入" />
+        </el-form-item>
+        <el-form-item label="期编号:">
+          <el-input v-model="formData.period" clearable placeholder="请输入" />
+        </el-form-item>
+        <el-form-item label="单位id:">
+          <el-input v-model.number="formData.unitId" clearable placeholder="请输入" />
+        </el-form-item>
+        <el-form-item label="关联问题id:">
+          <el-input v-model="formData.problemIds" clearable placeholder="请输入" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="closeDialog">取 消</el-button>
+          <el-button type="primary" @click="enterDialog">确 定</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <el-dialog v-model="dialogFormVisiblePro" :before-close="closeDialogPro" title="扣分详情">
+      <div>
+        <el-pagination
+          layout="total, sizes, prev, pager, next, jumper"
+          :current-page="pagePro"
+          :page-size="pageSizePro"
+          :page-sizes="[10, 30, 50, 100]"
+          :style="{float:'right',padding:'20px'}"
+          :total="totalPro"
+          @current-change="handleCurrentChangePro"
+          @size-change="handleSizeChangePro"
+        />
+        <el-table
+          ref="crudItem"
+          border
+          stripe
+          style="width: 100%"
+          tooltip-effect="dark"
+          :data="tableDataPro"
+        >
+          <el-table-column label="日期" width="180">
+            <template #default="scope">{{ formatDate(scope.row.CreatedAt) }}</template>
+          </el-table-column>
+          <el-table-column label="发布人" prop="oper" />
+          <el-table-column label="站点" prop="siteName" />
+          <el-table-column label="站点类型" prop="siteType">
+            <template #default="scope">
+              <dict-tag :options="dict.type.site_type" :value="scope.row.siteType" />
+            </template>
+          </el-table-column>
+          <el-table-column label="已登录查阅次数" prop="count" />
+          <el-table-column label="一类单位" prop="unitName" />
+          <el-table-column label="扣评分" prop="integral">
+            <template #default="scope">{{ scope.row.integral/10 }}</template>
+          </el-table-column>
+          <el-table-column label="处理状态" prop="status">
+            <template #default="scope">
+              <el-tag v-show="scope.row.status == 'Untreated'" type="warning">未处理</el-tag>
+              <el-tag v-show="scope.row.status == 'Processed'" type="success">已处理</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column label="责任部门" prop="department" />
+        </el-table>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  createUnitHistory,
+  deleteUnitHistory,
+  deleteUnitHistoryByIds,
+  updateUnitHistory,
+  findUnitHistory,
+  getUnitHistoryList
+} from '@/api/unitHistory' //  此处请自行替换地址
+import infoList from '@/mixins/infoList'
+import { getProblemInfoList } from '@/api/problemInfo'
+export default {
+  name: 'UnitHistory',
+  mixins: [infoList],
+  dicts: ['site_type'],
+  data() {
+    return {
+      listApi: getUnitHistoryList,
+      listProApi: getProblemInfoList,
+      dialogFormVisible: false,
+      type: '',
+      deleteVisible: false,
+      multipleSelection: [],
+      dialogFormVisiblePro: false,
+      tableDataPro: [],
+      pagePro: 1,
+      totalPro: 10,
+      pageSizePro: 10,
+      searchInfoPro: {
+        CreatedAtStart: new Date(),
+        CreatedAtEnd: new Date()
+      },
+      formData: {
+        unitName: '',
+        unitIntegral: 0,
+        unitMaxIntegral: 0,
+        period: '',
+        unitId: 0,
+        problemIds: '',
+      }
+    }
+  },
+  async created() {
+    await this.getTableData()
+  },
+  methods: {
+  // 条件搜索前端看此方法
+    onSubmit() {
+      this.page = 1
+      this.pageSize = 10
+      this.getTableData()
+    },
+    handleSelectionChange(val) {
+      this.multipleSelection = val
+    },
+    deleteRow(row) {
+      this.$confirm('确定要删除吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.deleteUnitHistory(row)
+      })
+    },
+    async onDelete() {
+      const ids = []
+      if (this.multipleSelection.length === 0) {
+        this.$message({
+          type: 'warning',
+          message: '请选择要删除的数据'
+        })
+        return
+      }
+      this.multipleSelection &&
+        this.multipleSelection.map(item => {
+          ids.push(item.ID)
+        })
+      const res = await deleteUnitHistoryByIds({ ids })
+      if (res.code === 0) {
+        this.$message({
+          type: 'success',
+          message: '删除成功'
+        })
+        if (this.tableData.length === ids.length && this.page > 1) {
+          this.page--
+        }
+        this.deleteVisible = false
+        this.getTableData()
+      }
+    },
+    async updateUnitHistory(row) {
+      const res = await findUnitHistory({ ID: row.ID })
+      this.type = 'update'
+      if (res.code === 0) {
+        this.formData = res.data.reunitHistory
+        this.dialogFormVisible = true
+      }
+    },
+    closeDialog() {
+      this.dialogFormVisible = false
+      this.formData = {
+        unitName: '',
+        unitIntegral: 0,
+        unitMaxIntegral: 0,
+        period: '',
+        unitId: 0,
+        problemIds: '',
+      }
+    },
+    async deleteUnitHistory(row) {
+      const res = await deleteUnitHistory({ ID: row.ID })
+      if (res.code === 0) {
+        this.$message({
+          type: 'success',
+          message: '删除成功'
+        })
+        if (this.tableData.length === 1 && this.page > 1) {
+          this.page--
+        }
+        this.getTableData()
+      }
+    },
+    async enterDialog() {
+      let res
+      switch (this.type) {
+        case 'create':
+          res = await createUnitHistory(this.formData)
+          break
+        case 'update':
+          res = await updateUnitHistory(this.formData)
+          break
+        default:
+          res = await createUnitHistory(this.formData)
+          break
+      }
+      if (res.code === 0) {
+        this.$message({
+          type: 'success',
+          message: '创建/更改成功'
+        })
+        this.closeDialog()
+        this.getTableData()
+      }
+    },
+    openDialog() {
+      this.type = 'create'
+      this.dialogFormVisible = true
+    },
+    openProDialog(row) {
+      this.dialogFormVisiblePro = true
+      console.log(row.period)
+      const formatDateStr = row.period.replace(/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/, '$1/$2/$3 $4:$5:$6')
+      // 将时间格式化成 yyyy-MM-dd HH:mm:ss
+      this.searchInfoPro.CreatedAtStart = new Date(formatDateStr)
+      this.searchInfoPro.CreatedAtEnd = new Date(row.CreatedAt)
+      this.searchInfoPro.unitId = row.unitId
+      console.log(this.searchInfoPro)
+      this.getTableDataPro()
+    },
+    handleSizeChangePro(val) {
+      this.pageSizePro = val
+      this.getTableDataPro()
+    },
+    handleCurrentChangePro(val) {
+      this.pagePro = val
+      this.getTableDataPro()
+    },
+    closeDialogPro() {
+      this.dialogFormVisiblePro = false
+      this.formData = {
+        unitName: '',
+        unitIntegral: 0,
+      }
+    },
+    getTableDataPro(page = this.pagePro, pageSize = this.pageSizePro) {
+      this.listProApi({ page, pageSize, ...this.searchInfoPro }).then(res => {
+        console.log(res)
+        if (res.code === 0) {
+          this.tableDataPro = res.data.list
+          this.totalPro = res.data.total
+          this.pagePro = res.data.page
+          this.pageSizePro = res.data.pageSize
+        }
+      })
+    }
+  },
+}
+</script>
+
+<style>
+</style>

+ 94 - 0
web/src/view/unitHistory/unitHistoryForm.vue

@@ -0,0 +1,94 @@
+<template>
+  <div>
+    <el-form :model="formData" label-position="right" label-width="80px">
+      <el-form-item label="单位名称:">
+        <el-input v-model="formData.unitName" clearable placeholder="请输入" />
+      </el-form-item>
+      <el-form-item label="现有积分:">
+        <el-input v-model.number="formData.unitIntegral" clearable placeholder="请输入" />
+      </el-form-item>
+      <el-form-item label="满分:">
+        <el-input v-model.number="formData.unitMaxIntegral" clearable placeholder="请输入" />
+      </el-form-item>
+      <el-form-item label="期编号:">
+        <el-input v-model="formData.period" clearable placeholder="请输入" />
+      </el-form-item>
+      <el-form-item label="单位id:">
+        <el-input v-model.number="formData.unitId" clearable placeholder="请输入" />
+      </el-form-item>
+      <el-form-item label="关联问题id:">
+        <el-input v-model="formData.problemIds" clearable placeholder="请输入" />
+      </el-form-item>
+      <el-form-item>
+        <el-button size="mini" type="primary" @click="save">保存</el-button>
+        <el-button size="mini" type="primary" @click="back">返回</el-button>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import {
+  createUnitHistory,
+  updateUnitHistory,
+  findUnitHistory
+} from '@/api/unitHistory' //  此处请自行替换地址
+import infoList from '@/mixins/infoList'
+export default {
+  name: 'UnitHistory',
+  mixins: [infoList],
+  data() {
+    return {
+      type: '',
+      formData: {
+        unitName: '',
+        unitIntegral: 0,
+        unitMaxIntegral: 0,
+        period: '',
+        unitId: 0,
+        problemIds: '',
+      }
+    }
+  },
+  async created() {
+    // 建议通过url传参获取目标数据ID 调用 find方法进行查询数据操作 从而决定本页面是create还是update 以下为id作为url参数示例
+    if (this.$route.query.id) {
+      const res = await findUnitHistory({ ID: this.$route.query.id })
+      if (res.code === 0) {
+        this.formData = res.data.reunitHistory
+        this.type = 'update'
+      }
+    } else {
+      this.type = 'create'
+    }
+  },
+  methods: {
+    async save() {
+      let res
+      switch (this.type) {
+        case 'create':
+          res = await createUnitHistory(this.formData)
+          break
+        case 'update':
+          res = await updateUnitHistory(this.formData)
+          break
+        default:
+          res = await createUnitHistory(this.formData)
+          break
+      }
+      if (res.code === 0) {
+        this.$message({
+          type: 'success',
+          message: '创建/更改成功'
+        })
+      }
+    },
+    back() {
+      this.$router.go(-1)
+    }
+  }
+}
+</script>
+
+<style>
+</style>