Selaa lähdekoodia

forage: 数据导入

Yi 1 vuosi sitten
vanhempi
commit
39092d4145

+ 11 - 2
backend/operation/enum.proto

@@ -60,6 +60,15 @@ message ForagePlanType {
   enum Kind {
     INVALID = 0;           // 无
     FORKLIFT = 1;          // 铲车
-    CONCENTRATE = 2;     // 精料
+    CONCENTRATE = 2;       // 精料
   }
-}
+}
+
+message DataSource {
+  enum Kind {
+    INVALID = 0;           // 无
+    BACKGROUND_ADD = 1;    // 后台手动添加
+    EXCEL_IMPORT = 2;     // excel报表导入
+    FROM_PASTURE = 3;     // 来自牧场
+  }
+}

+ 7 - 12
backend/operation/pasture.proto

@@ -7,14 +7,14 @@ import "backend/operation/enum.proto";
 import "backend/operation/pagination.proto";
 
 message AddPastureRequest {
-  uint32 id = 1;
+  int32 id = 1;
   string name = 2; // 牧场名称
   string account = 3;   // 登录账号名称
   string manager_user = 4; // 牧场负责人名称
   string manager_phone = 5;   // 牧场负责人手机号
   string address = 6;   // 牧场地址
   IsShow.Kind is_show = 7;    // 是否启用
-  uint32 created_at = 8;    // 创建时间
+  int32 created_at = 8;    // 创建时间
   string created_at_format = 9;    // 创建时间格式化
 }
 
@@ -36,17 +36,12 @@ message SearchPastureResponse {
 message SearchPastureData {
   int32 page = 1;
   int32 total = 2;
-  repeated AddPastureRequest list = 3;
-}
-
-// 重置牧场登录密码
-message RestPasswordGroupPasture {
-  uint32 pasture_id = 1;    // 牧场id
-  string password = 2;     // 密码(md5加密过的)
+  int32 page_size = 3;
+  repeated AddPastureRequest list = 4;
 }
 
 message IsShowGroupPasture {
-  uint32 pasture_id = 1;    // 牧场id
+  int32 pasture_id = 1;    // 牧场id
   IsShow.Kind is_show = 2;     // 是否开启
 }
 
@@ -64,7 +59,7 @@ message AddCattleCategoryRequest {
 
 // 是否启用
 message IsShowCattleCategory {
-  uint32 cattle_category_id = 1;
+  int32 cattle_category_id = 1;
   IsShow.Kind is_show = 2;
 }
 
@@ -102,7 +97,7 @@ message AddForageCategoryRequest {
 
 // 是否启用
 message IsShowForageCategory {
-  uint32 forage_category_id = 1;
+  int32 forage_category_id = 1;
   IsShow.Kind is_show = 2;
 }
 

+ 17 - 9
backend/operation/system.proto

@@ -89,21 +89,30 @@ message UserAuthData {
 }
 
 message UserRole {
-  uint32 id = 1;      // 角色id
+  int32 id = 1;      // 角色id
   string name = 2;   // 角色名称
 }
 
+// 用户详情
+message UserDetails {
+  int32 code = 1;
+  string msg = 2;
+  AddSystemUser data = 3;
+}
+
+
 message AddSystemUser {
-  uint32 id = 1;                    // 用户id
+  int32 id = 1;                    // 用户id
   string name = 2;                 // 用户名称
   string phone = 3;                // 用户手机号
   repeated UserRole roles = 4;      // 角色
   IsShow.Kind is_show = 5;         // 是否开启
   string employee_name = 6;        // 员工姓名
   string create_user = 7;          // 创建人
-  uint32 created_at = 8;            // 创建时间
+  int32 created_at = 8;            // 创建时间
   string created_at_format = 9;      // 创建时间格式化
   string role_name = 10;            // 角色名称
+  repeated int32 role_ids = 11;     // 角色ids
 }
 
 // 查询用户
@@ -130,15 +139,14 @@ message SearchUserData  {
 }
 
 message IsShowSystemUserRequest {
-  uint32 user_id = 1;  // 用户id
+  int32 user_id = 1;  // 用户id
   IsShow.Kind is_show = 2;   // is_show
 }
-
 // 系统菜单权限
 message AddMenuRequest {
-  uint32 id = 1;
+  int32 id = 1;
   string name = 2;           // 名称
-  uint32 parent_id = 3;       // 父id
+  int32 parent_id = 3;       // 父id
   int32 menu_type = 4;       // 菜单类型 1 菜单 2 按钮
   string title = 5;          // 标题
   string path = 6;           // 路径 path
@@ -147,7 +155,7 @@ message AddMenuRequest {
   string icon = 9;           // 图标
   int32 sort = 10;           // 排序
   string redirect = 11;      // 重定向
-  uint32 created_at = 12;     // 创建时间
+  int32 created_at = 12;     // 创建时间
   string created_at_format = 13;      // 创建时间格式化
   int32 level = 14;                   // 菜单等级
   repeated AddMenuRequest children = 15;   // 子分类
@@ -156,7 +164,7 @@ message AddMenuRequest {
 }
 
 message IsShowSystemMenuRequest {
-  uint32 menu_id = 1;  // 角色id
+  int32 menu_id = 1;  // 角色id
   IsShow.Kind is_show = 2;   // is_show
 }
 

+ 0 - 2
dep/dep.go

@@ -4,7 +4,6 @@ import (
 	"kpt-tmr-group/config"
 	"kpt-tmr-group/module/backend"
 	"kpt-tmr-group/pkg/di"
-	"kpt-tmr-group/service/excel"
 	"kpt-tmr-group/service/sso"
 	"kpt-tmr-group/store/kptstore"
 )
@@ -26,6 +25,5 @@ func Options() []di.HubOption {
 		kptstore.Module,
 		backend.Module,
 		sso.Module,
-		excel.Module,
 	}
 }

+ 59 - 10
http/handler/pasture/forage_list.go

@@ -1,13 +1,17 @@
 package pasture
 
 import (
+	"fmt"
 	"kpt-tmr-group/http/middleware"
 	"kpt-tmr-group/pkg/apierr"
 	"kpt-tmr-group/pkg/ginutil"
 	"kpt-tmr-group/pkg/valid"
 	"kpt-tmr-group/pkg/xerr"
 	operationPb "kpt-tmr-group/proto/go/backend/operation"
+	"mime/multipart"
 	"net/http"
+	"path"
+	"time"
 
 	"github.com/gin-gonic/gin"
 )
@@ -149,21 +153,35 @@ func IsShowForage(c *gin.Context) {
 	})
 }
 
-func ImportForage(c *gin.Context) {
-	if err := func(c *gin.Context) error {
-		if c.ContentType() != "application/octet-stream" {
-			return xerr.Custom("invalid Content-Type")
+func ExcelImportForage(c *gin.Context) {
+
+	file, err := func(c *gin.Context) (multipart.File, error) {
+		if c.ContentType() != "multipart/form-data" {
+			return nil, xerr.Custom("invalid Content-Type")
 		}
 		if c.Request.Body == nil || int(c.Request.ContentLength) <= 0 {
-			return xerr.Custom("invalid body")
+			return nil, xerr.Custom("invalid body")
+		}
+
+		file, fileHeader, err := c.Request.FormFile("file")
+		if err != nil {
+			return nil, xerr.WithStack(err)
+		}
+
+		fileSuffix := path.Ext(path.Base(fileHeader.Filename))
+		if fileSuffix != ".xlsx" {
+			return nil, xerr.Custom("invalid file suffix")
 		}
-		return nil
-	}(c); err != nil {
+
+		return file, nil
+	}(c)
+
+	if err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
 		return
 	}
 
-	if err := middleware.BackendOperation(c).OpsService.ImportForage(c); err != nil {
+	if err = middleware.BackendOperation(c).OpsService.ExcelImportForage(c, file); err != nil {
 		apierr.ClassifiedAbort(c, err)
 		return
 	}
@@ -174,7 +192,8 @@ func ImportForage(c *gin.Context) {
 	})
 }
 
-func ExportForage(c *gin.Context) {
+func ExcelExportForage(c *gin.Context) {
+
 	req := &operationPb.SearchForageListRequest{}
 	if err := c.BindJSON(req); err != nil {
 		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
@@ -187,7 +206,37 @@ func ExportForage(c *gin.Context) {
 		PageOffset: int32(c.GetInt(middleware.PageOffset)),
 	}
 
-	if err := middleware.BackendOperation(c).OpsService.ExportForage(c, req); err != nil {
+	buffer, err := middleware.BackendOperation(c).OpsService.ExcelExportForage(c, req)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+
+	c.Header("Content-Type", "application/octet-stream")
+	c.Header("Content-Disposition", "attachment; filename="+(fmt.Sprintf("饲料表 %s.xlsx", time.Now().Format("200601021504"))))
+	if _, err = c.Writer.Write(buffer.Bytes()); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
+}
+
+func ExcelTemplateForage(c *gin.Context) {
+
+	buffer, err := middleware.BackendOperation(c).OpsService.ExcelTemplateForage(c)
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+
+	c.Header("Content-Type", "application/octet-stream")
+	c.Header("Content-Disposition", "attachment; filename="+(fmt.Sprintf("饲料表 %s.xlsx", time.Now().Format("200601021504"))))
+	if _, err = c.Writer.Write(buffer.Bytes()); err != nil {
 		apierr.ClassifiedAbort(c, err)
 		return
 	}

+ 5 - 10
http/handler/pasture/pasture_list.go

@@ -114,20 +114,15 @@ func DeleteGroupPasture(c *gin.Context) {
 }
 
 func ResetPasswordGroupPasture(c *gin.Context) {
-	var req operationPb.RestPasswordGroupPasture
-	if err := ginutil.BindProto(c, &req); err != nil {
-		apierr.AbortBadRequest(c, http.StatusBadRequest, err)
-		return
-	}
-	if err := valid.ValidateStruct(&req,
-		valid.Field(&req.PastureId, valid.Required, valid.Min(1)),
-		valid.Field(&req.Password, valid.Required),
-	); err != nil {
+	pastureIdStr := c.Param("pasture_id")
+	pastureId, _ := strconv.Atoi(pastureIdStr)
+
+	if err := valid.Validate(pastureId, valid.Required, valid.Min(1)); err != nil {
 		apierr.ClassifiedAbort(c, err)
 		return
 	}
 
-	if err := middleware.BackendOperation(c).OpsService.ResetPasswordGroupPasture(c, &req); err != nil {
+	if err := middleware.BackendOperation(c).OpsService.ResetPasswordGroupPasture(c, int64(pastureId)); err != nil {
 		apierr.ClassifiedAbort(c, err)
 		return
 	}

+ 0 - 1
http/handler/system/menu.go

@@ -61,7 +61,6 @@ func EditSystemMenu(c *gin.Context) {
 	if err := valid.ValidateStruct(&req,
 		valid.Field(&req.Id, valid.Required, valid.Min(1)),
 		valid.Field(&req.Name, valid.Required),
-		valid.Field(&req.ParentId, valid.Required, valid.Min(0)),
 		valid.Field(&req.MenuType, valid.Required, valid.Min(0), valid.Max(2)),
 		valid.Field(&req.Path, valid.Required),
 	); err != nil {

+ 41 - 0
http/handler/system/user.go

@@ -67,6 +67,25 @@ func AddSystemUser(c *gin.Context) {
 	})
 }
 
+// DetailsSystemUser 系统用户详情
+func DetailsSystemUser(c *gin.Context) {
+	userIdStr := c.Param("user_id")
+	userId, _ := strconv.Atoi(userIdStr)
+
+	if err := valid.Validate(userId, valid.Required, valid.Min(1)); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+
+	res, err := middleware.BackendOperation(c).OpsService.DetailsSystemUser(c, int64(userId))
+	if err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+
+	ginutil.JSONResp(c, res)
+}
+
 // GetUserInfo 获取用户信息
 func GetUserInfo(c *gin.Context) {
 	token := middleware.GetToken(c)
@@ -206,3 +225,25 @@ func GetSystemUserPermissions(c *gin.Context) {
 	}
 	ginutil.JSONResp(c, res)
 }
+
+// ResetPasswordSystemUser 用户密码重置
+func ResetPasswordSystemUser(c *gin.Context) {
+	userIdStr := c.Param("user_id")
+	userId, _ := strconv.Atoi(userIdStr)
+
+	if err := valid.Validate(userId, valid.Required, valid.Min(1)); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+
+	if err := middleware.BackendOperation(c).OpsService.ResetPasswordSystemUser(c, int64(userId)); err != nil {
+		apierr.ClassifiedAbort(c, err)
+		return
+	}
+
+	ginutil.JSONResp(c, &operationPb.CommonOK{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: &operationPb.Success{Success: true},
+	})
+}

+ 6 - 3
http/route/app_api.go

@@ -27,11 +27,13 @@ func AppAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		systemRoute := authRouteGroup(s, "/api/v1/system/")
 		systemRoute.POST("/user_info", system.GetUserInfo)
 		systemRoute.POST("/user/add", system.AddSystemUser)
+		systemRoute.GET("/user/details/:user_id", system.DetailsSystemUser)
 		systemRoute.POST("/user/list", system.SearchSystemUserList)
 		systemRoute.POST("/user/edit", system.EditSystemUser)
 		systemRoute.POST("/user/is_show", system.IsShowSystemUser)
 		systemRoute.DELETE("/user/:user_id", system.DeleteUser)
 		systemRoute.POST("/user/permissions", system.GetSystemUserPermissions)
+		systemRoute.POST("/user/rest_password/:user_id", system.ResetPasswordSystemUser)
 
 		// 系统角色
 		systemRoute.POST("/role/add", system.AddSystemRole)
@@ -56,7 +58,7 @@ func AppAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		opsRoute.POST("/pasture/edit", pasture.EditGroupPasture)
 		opsRoute.POST("/pasture/list", pasture.SearchGroupPastureList)
 		opsRoute.DELETE("/pasture/:pasture_id", pasture.DeleteGroupPasture)
-		opsRoute.POST("/pasture/rest_password", pasture.ResetPasswordGroupPasture)
+		opsRoute.POST("/pasture/rest_password/:pasture_id", pasture.ResetPasswordGroupPasture)
 		opsRoute.POST("/pasture/is_show", pasture.IsShowGroupPasture)
 
 		// 牲牧类型
@@ -81,8 +83,9 @@ func AppAPI(opts ...func(engine *gin.Engine)) func(s *gin.Engine) {
 		opsRoute.POST("/forage/list", pasture.SearchForageList)
 		opsRoute.POST("forage/delete", pasture.DeleteForageList)
 		opsRoute.POST("forage/is_show", pasture.IsShowForage)
-		opsRoute.POST("forage/import", pasture.ImportForage)
-		opsRoute.POST("forage/export", pasture.ExportForage)
+		opsRoute.POST("forage/excel_import", pasture.ExcelImportForage)
+		opsRoute.POST("forage/excel_export", pasture.ExcelExportForage)
+		opsRoute.POST("forage/excel_template", pasture.ExcelTemplateForage)
 		opsRoute.GET("/forage/enum/list", pasture.SearchForageEnumList)
 	}
 }

+ 0 - 3
logger/zap-2023-05-06.log

@@ -1,3 +0,0 @@
-{"L":"ERROR","T":"2023-05-06T16:51:38.918+0800","M":"MustNewStore","Err":"Error 1045 (28000): Access denied for user 'root'@'172.19.0.1' (using password: NO)","KptEventDSNRW":"root@tcp(127.0.0.1:3306)/kpt_tmr_group?charset=utf8mb4&parseTime=true&loc=Local&allowNativePasswords=true&timeout=300s&readTimeout=300s&writeTimeout=300s","func":"kptstore.MustNewStore","file":"D:/project/golangNew/kpt-tmr-group/store/kptstore/rw_store.go","line":53}
-{"L":"ERROR","T":"2023-05-06T16:54:30.471+0800","M":"MustNewStore","Err":"Error 1049 (42000): Unknown database 'kpt_tmr-group'","KptEventDSNRW":"root:123456@tcp(192.168.1.70:3306)/kpt_tmr-group?charset=utf8mb4&parseTime=true&loc=Local&allowNativePasswords=true&timeout=300s&readTimeout=300s&writeTimeout=300s","func":"kptstore.MustNewStore","file":"D:/project/golangNew/kpt-tmr-group/store/kptstore/rw_store.go","line":53}
-{"L":"ERROR","T":"2023-05-06T16:54:56.679+0800","M":"MustNewStore","Err":"Error 1049 (42000): Unknown database 'kpt_tmr-group'","KptEventDSNRW":"root:123456@tcp(127.0.0.1:3306)/kpt_tmr-group?charset=utf8mb4&parseTime=true&loc=Local&allowNativePasswords=true&timeout=300s&readTimeout=300s&writeTimeout=300s","func":"kptstore.MustNewStore","file":"D:/project/golangNew/kpt-tmr-group/store/kptstore/rw_store.go","line":53}

+ 12 - 9
model/cattle_category.go

@@ -6,15 +6,18 @@ import (
 )
 
 type CattleCategory struct {
-	Id         int64                                 `json:"id"`
-	ParentId   operationPb.CattleCategoryParent_Kind `json:"parent_id"`
-	ParentName string                                `json:"parent_name"`
-	Name       string                                `json:"name"`
-	Number     string                                `json:"number"`
-	IsShow     operationPb.IsShow_Kind               `json:"is_show"`
-	IsDelete   operationPb.IsShow_Kind               `json:"is_delete"`
-	CreatedAt  int64                                 `json:"created_at"`
-	UpdatedAt  int64                                 `json:"updated_at"`
+	Id          int64                                 `json:"id"`
+	ParentId    operationPb.CattleCategoryParent_Kind `json:"parent_id"`
+	ParentName  string                                `json:"parent_name"`
+	PastureId   int64                                 `json:"pasture_id"`
+	PastureName string                                `json:"pasture_name"`
+	Name        string                                `json:"name"`
+	Number      string                                `json:"number"`
+	IsShow      operationPb.IsShow_Kind               `json:"is_show"`
+	IsDelete    operationPb.IsShow_Kind               `json:"is_delete"`
+	DataSource  operationPb.DataSource_Kind           `json:"data_source"`
+	CreatedAt   int64                                 `json:"created_at"`
+	UpdatedAt   int64                                 `json:"updated_at"`
 }
 
 func (c *CattleCategory) TableName() string {

+ 2 - 0
model/forage.go

@@ -22,6 +22,7 @@ type Forage struct {
 	ConfirmStart       operationPb.IsShow_Kind         `json:"confirm_start"`
 	RelayLocations     int64                           `json:"relay_locations"`
 	Jmp                operationPb.IsShow_Kind         `json:"jmp"`
+	DataSource         operationPb.DataSource_Kind     `json:"data_source"`
 	Backup1            string                          `json:"backup1"`
 	Backup2            string                          `json:"backup2"`
 	Backup3            string                          `json:"backup3"`
@@ -52,6 +53,7 @@ func NewForage(req *operationPb.AddForageRequest) *Forage {
 		RelayLocations:     int64(req.RelayLocations),
 		IsShow:             operationPb.IsShow_OK,
 		IsDelete:           operationPb.IsShow_OK,
+		DataSource:         operationPb.DataSource_BACKGROUND_ADD,
 		Jmp:                req.Jmp,
 		Backup1:            req.Backup1,
 		Backup2:            req.Backup2,

+ 12 - 9
model/forage_category.go

@@ -6,15 +6,18 @@ import (
 )
 
 type ForageCategory struct {
-	Id         int64                                 `json:"id"`
-	ParentId   operationPb.ForageCategoryParent_Kind `json:"parent_id"`
-	ParentName string                                `json:"parent_name"`
-	Name       string                                `json:"name"`
-	Number     string                                `json:"number"`
-	IsShow     operationPb.IsShow_Kind               `json:"is_show"`
-	IsDelete   operationPb.IsShow_Kind               `json:"is_delete"`
-	CreatedAt  int64                                 `json:"created_at"`
-	UpdatedAt  int64                                 `json:"updated_at"`
+	Id          int64                                 `json:"id"`
+	ParentId    operationPb.ForageCategoryParent_Kind `json:"parent_id"`
+	ParentName  string                                `json:"parent_name"`
+	PastureId   int64                                 `json:"pasture_id"`
+	PastureName string                                `json:"pasture_name"`
+	Name        string                                `json:"name"`
+	Number      string                                `json:"number"`
+	IsShow      operationPb.IsShow_Kind               `json:"is_show"`
+	IsDelete    operationPb.IsShow_Kind               `json:"is_delete"`
+	DataSource  operationPb.DataSource_Kind           `json:"data_source"`
+	CreatedAt   int64                                 `json:"created_at"`
+	UpdatedAt   int64                                 `json:"updated_at"`
 }
 
 func (s *ForageCategory) TableName() string {

+ 6 - 4
model/group_pasture.go

@@ -34,6 +34,7 @@ func NewGroupPasture(req *operationPb.AddPastureRequest) *GroupPasture {
 		ManagerUser:  req.ManagerUser,
 		ManagerPhone: req.ManagerPhone,
 		IsShow:       operationPb.IsShow_OK,
+		IsDelete:     operationPb.IsShow_OK,
 		Address:      req.Address,
 	}
 	return groupPasture
@@ -45,13 +46,14 @@ func (g GroupPastureSlice) ToPB() []*operationPb.AddPastureRequest {
 	res := make([]*operationPb.AddPastureRequest, len(g))
 	for i, v := range g {
 		res[i] = &operationPb.AddPastureRequest{
-			Id:              uint32(v.Id),
+			Id:              int32(v.Id),
 			Name:            v.Name,
+			Account:         v.Account,
 			ManagerUser:     v.ManagerUser,
 			ManagerPhone:    v.ManagerPhone,
 			Address:         v.Address,
 			IsShow:          v.IsShow,
-			CreatedAt:       uint32(v.CreatedAt),
+			CreatedAt:       int32(v.CreatedAt),
 			CreatedAtFormat: time.Unix(v.CreatedAt, 0).Format(LayoutTime),
 		}
 	}
@@ -60,12 +62,12 @@ func (g GroupPastureSlice) ToPB() []*operationPb.AddPastureRequest {
 
 func (g *GroupPasture) ToPb() *operationPb.AddPastureRequest {
 	return &operationPb.AddPastureRequest{
-		Id:           uint32(g.Id),
+		Id:           int32(g.Id),
 		Name:         g.Name,
 		ManagerUser:  g.ManagerUser,
 		ManagerPhone: g.ManagerPhone,
 		Address:      g.Address,
 		IsShow:       g.IsShow,
-		CreatedAt:    uint32(g.CreatedAt),
+		CreatedAt:    int32(g.CreatedAt),
 	}
 }

+ 6 - 6
model/system_menu.go

@@ -59,9 +59,9 @@ func (s SystemMenuSlice) ToPB() []*operationPb.AddMenuRequest {
 			level[menu.Level] = make([]*operationPb.AddMenuRequest, 0)
 		}
 		level[menu.Level] = append(level[menu.Level], &operationPb.AddMenuRequest{
-			Id:              uint32(menu.Id),
+			Id:              int32(menu.Id),
 			Name:            menu.Name,
-			ParentId:        uint32(menu.ParentId),
+			ParentId:        int32(menu.ParentId),
 			MenuType:        menu.MenuType,
 			Title:           menu.Title,
 			Path:            menu.Path,
@@ -70,7 +70,7 @@ func (s SystemMenuSlice) ToPB() []*operationPb.AddMenuRequest {
 			Icon:            menu.Icon,
 			Sort:            menu.Sort,
 			Redirect:        menu.Redirect,
-			CreatedAt:       uint32(menu.CreatedAt),
+			CreatedAt:       int32(menu.CreatedAt),
 			CreatedAtFormat: time.Unix(menu.CreatedAt, 0).Format(LayoutTime),
 			Level:           menu.Level,
 			Affix:           true,
@@ -106,7 +106,7 @@ func (s SystemMenuSlice) ToPB() []*operationPb.AddMenuRequest {
 
 func (s *SystemMenu) ToPb() *operationPb.AddMenuRequest {
 	return &operationPb.AddMenuRequest{
-		Id:              uint32(s.Id),
+		Id:              int32(s.Id),
 		Name:            s.Name,
 		MenuType:        s.MenuType,
 		Level:           s.Level,
@@ -116,9 +116,9 @@ func (s *SystemMenu) ToPb() *operationPb.AddMenuRequest {
 		Icon:            s.Icon,
 		Sort:            s.Sort,
 		Redirect:        s.Redirect,
-		ParentId:        uint32(s.ParentId),
+		ParentId:        int32(s.ParentId),
 		IsShow:          s.IsShow,
-		CreatedAt:       uint32(s.CreatedAt),
+		CreatedAt:       int32(s.CreatedAt),
 		CreatedAtFormat: time.Unix(s.CreatedAt, 0).Format(LayoutTime),
 	}
 }

+ 20 - 10
model/system_user.go

@@ -31,7 +31,7 @@ func (s *SystemUser) SystemUserFormat(userRoles []*SystemRole) *operationPb.User
 	roles := make([]*operationPb.UserRole, len(userRoles))
 	for k, v := range userRoles {
 		roles[k] = &operationPb.UserRole{
-			Id:   uint32(v.Id),
+			Id:   int32(v.Id),
 			Name: v.Name,
 		}
 	}
@@ -77,13 +77,13 @@ func (s SystemUserSlice) ToPB(roleList []*SystemRole) []*operationPb.AddSystemUs
 	res := make([]*operationPb.AddSystemUser, len(s))
 	for i, v := range s {
 		res[i] = &operationPb.AddSystemUser{
-			Id:              uint32(v.Id),
+			Id:              int32(v.Id),
 			Name:            v.Name,
 			Phone:           v.Phone,
 			EmployeeName:    v.EmployeeName,
 			CreateUser:      v.CreateUser,
 			IsShow:          v.IsShow,
-			CreatedAt:       uint32(v.CreatedAt),
+			CreatedAt:       int32(v.CreatedAt),
 			CreatedAtFormat: time.Unix(v.CreatedAt, 0).Format(LayoutTime),
 			RoleName:        strings.TrimRight(v.UserRoleFormat(roleList), ","),
 		}
@@ -106,13 +106,23 @@ func (s *SystemUser) UserRoleFormat(roleList []*SystemRole) string {
 }
 
 func (s *SystemUser) ToPb() *operationPb.AddSystemUser {
+
+	roles := make([]int32, 0)
+	roleIds := strings.Split(s.RoleIds, ",")
+	for _, roleId := range roleIds {
+		id, _ := strconv.Atoi(roleId)
+		roles = append(roles, int32(id))
+	}
+
 	return &operationPb.AddSystemUser{
-		Id:           uint32(s.Id),
-		Name:         s.Name,
-		Phone:        s.Phone,
-		CreateUser:   s.CreateUser,
-		EmployeeName: s.EmployeeName,
-		IsShow:       s.IsShow,
-		CreatedAt:    uint32(s.CreatedAt),
+		Id:              int32(s.Id),
+		Name:            s.Name,
+		Phone:           s.Phone,
+		CreateUser:      s.CreateUser,
+		EmployeeName:    s.EmployeeName,
+		IsShow:          s.IsShow,
+		CreatedAt:       int32(s.CreatedAt),
+		CreatedAtFormat: time.Unix(s.CreatedAt, 0).Format(LayoutTime),
+		RoleIds:         roles,
 	}
 }

+ 8 - 7
module/backend/interface.go

@@ -1,15 +1,14 @@
 package backend
 
 import (
+	"bytes"
 	"context"
+	"io"
 	"kpt-tmr-group/config"
 	"kpt-tmr-group/pkg/di"
 	operationPb "kpt-tmr-group/proto/go/backend/operation"
-	"kpt-tmr-group/service/excel"
 	"kpt-tmr-group/store/kptstore"
 
-	"github.com/gin-gonic/gin"
-
 	"go.uber.org/dig"
 )
 
@@ -28,7 +27,6 @@ type StoreEntry struct {
 	//SSO *sso.Cache
 	// AsynqClient asynqsvc.Client
 	// Cache *redis.Client
-	ExcelClient *excel.ExcelServer
 }
 
 func NewStore(store StoreEntry) KptService {
@@ -46,7 +44,7 @@ type Operation interface {
 	EditGroupPasture(ctx context.Context, req *operationPb.AddPastureRequest) error
 	SearchGroupPastureList(ctx context.Context, req *operationPb.SearchPastureRequest) (*operationPb.SearchPastureResponse, error)
 	DeleteGroupPasture(ctx context.Context, pastureId int64) error
-	ResetPasswordGroupPasture(ctx context.Context, req *operationPb.RestPasswordGroupPasture) error
+	ResetPasswordGroupPasture(ctx context.Context, pastureId int64) error
 	IsShowGroupPasture(ctx context.Context, req *operationPb.IsShowGroupPasture) error
 
 	// ParentCattleCategoryList 牧畜类别
@@ -72,8 +70,9 @@ type Operation interface {
 	ForageEnumList(ctx context.Context) *operationPb.ForageEnumList
 	DeleteForageList(ctx context.Context, ids []int64) error
 	IsShowForage(ctx context.Context, req *operationPb.IsShowForage) error
-	ImportForage(ctx context.Context) error
-	ExportForage(ctx *gin.Context, req *operationPb.SearchForageListRequest) error
+	ExcelImportForage(ctx context.Context, req io.Reader) error
+	ExcelExportForage(ctx context.Context, req *operationPb.SearchForageListRequest) (*bytes.Buffer, error)
+	ExcelTemplateForage(ctx context.Context) (*bytes.Buffer, error)
 }
 
 type SystemOperation interface {
@@ -84,6 +83,8 @@ type SystemOperation interface {
 	SearchSystemUserList(ctx context.Context, req *operationPb.SearchUserRequest) (*operationPb.SearchUserResponse, error)
 	EditSystemUser(ctx context.Context, req *operationPb.AddSystemUser) error
 	DeleteSystemUser(ctx context.Context, userId int64) error
+	ResetPasswordSystemUser(ctx context.Context, userId int64) error
+	DetailsSystemUser(ctx context.Context, userId int64) (*operationPb.UserDetails, error)
 	IsShowSystemUser(ctx context.Context, req *operationPb.IsShowSystemUserRequest) error
 	GetSystemUserPermissions(ctx context.Context, token string) (*operationPb.SystemUserMenuPermissions, error)
 

+ 174 - 24
module/backend/pasture_service.go

@@ -1,15 +1,22 @@
 package backend
 
 import (
+	"bytes"
 	"context"
 	"errors"
 	"fmt"
+	"io"
 	"kpt-tmr-group/model"
+	"kpt-tmr-group/pkg/logger/zaplog"
+	"kpt-tmr-group/pkg/tool"
 	"kpt-tmr-group/pkg/xerr"
 	operationPb "kpt-tmr-group/proto/go/backend/operation"
 	"net/http"
+	"strconv"
 
-	"github.com/gin-gonic/gin"
+	"go.uber.org/zap"
+
+	"github.com/xuri/excelize/v2"
 
 	"gorm.io/gorm"
 )
@@ -115,9 +122,10 @@ func (s *StoreEntry) SearchGroupPastureList(ctx context.Context, req *operationP
 		Code: http.StatusOK,
 		Msg:  "ok",
 		Data: &operationPb.SearchPastureData{
-			Page:  req.Pagination.Page,
-			Total: int32(count),
-			List:  model.GroupPastureSlice(groupPasture).ToPB(),
+			Page:     req.Pagination.Page,
+			Total:    int32(count),
+			PageSize: req.Pagination.PageSize,
+			List:     model.GroupPastureSlice(groupPasture).ToPB(),
 		},
 	}, nil
 }
@@ -139,18 +147,18 @@ func (s *StoreEntry) DeleteGroupPasture(ctx context.Context, pastureId int64) er
 	return nil
 }
 
-func (s *StoreEntry) ResetPasswordGroupPasture(ctx context.Context, req *operationPb.RestPasswordGroupPasture) error {
+func (s *StoreEntry) ResetPasswordGroupPasture(ctx context.Context, pastureId int64) error {
 	groupPasture := &model.GroupPasture{
-		Id: int64(req.PastureId),
+		Id: pastureId,
 	}
-	if err := s.DB.First(groupPasture).Error; err != nil {
+	if err := s.DB.Where("is_delete = ?", operationPb.IsShow_OK).First(groupPasture).Error; err != nil {
 		if errors.Is(err, gorm.ErrRecordNotFound) {
 			return xerr.Custom("该数据不存在")
 		}
 		return xerr.WithStack(err)
 	}
 
-	if err := s.DB.Model(groupPasture).Update("password", req.Password).Error; err != nil {
+	if err := s.DB.Model(groupPasture).Update("password", tool.Md5String(model.InitManagerPassword)).Error; err != nil {
 		return xerr.WithStack(err)
 	}
 	return nil
@@ -167,7 +175,7 @@ func (s *StoreEntry) IsShowGroupPasture(ctx context.Context, req *operationPb.Is
 		return xerr.WithStack(err)
 	}
 
-	if err := s.DB.Model(groupPasture).Update("is_show", req.IsShow).Error; err != nil {
+	if err := s.DB.Model(groupPasture).Where("is_delete = ?", operationPb.IsShow_OK).Update("is_show", req.IsShow).Error; err != nil {
 		return xerr.WithStack(err)
 	}
 	return nil
@@ -487,10 +495,6 @@ func (s *StoreEntry) ForageEnumList(ctx context.Context) *operationPb.ForageEnum
 		IsShow:               make([]*operationPb.IsShowEnum, 0),
 	}
 
-	// operationPb.JumpDelaType_INVALID: "禁用",
-	//		operationPb.JumpDelaType_THREE:   "3秒",
-	//		operationPb.JumpDelaType_SIX:     "6秒",
-	//		operationPb.JumpDelaType_NINE:    "9秒",
 	res.JumpDelaType = append(res.JumpDelaType, &operationPb.JumpDelaTypeEnum{
 		Value: operationPb.JumpDelaType_INVALID,
 		Label: "禁用",
@@ -530,28 +534,174 @@ func (s *StoreEntry) IsShowForage(ctx context.Context, req *operationPb.IsShowFo
 	return nil
 }
 
-func (s *StoreEntry) ImportForage(ctx context.Context) error {
+// ExcelImportForage 导入excel
+func (s *StoreEntry) ExcelImportForage(ctx context.Context, req io.Reader) error {
+	xlsx, err := excelize.OpenReader(req)
+	if err != nil {
+		return xerr.WithStack(err)
+	}
+	defer xlsx.Close()
+
+	rows, err := xlsx.GetRows(xlsx.GetSheetName(xlsx.GetActiveSheetIndex()))
+	if err != nil {
+		return xerr.WithStack(err)
+	}
+
+	if len(rows) > 10000 {
+		rows = rows[:10000]
+	}
+	forageList := make([]*model.Forage, 0)
+	for i, row := range rows {
+		if i == 0 {
+			continue
+		}
+		var (
+			forageSourceId                                int32
+			categoryId, price, jumpWeight, relayLocations int
+			allowError, packageWeight                     int
+			backup1, backup2, backup3                     string
+		)
+
+		for k, v := range row {
+			if k == 3 {
+				forageSourceId = operationPb.ForageSource_Kind_value[v]
+			}
+			if k == 5 {
+				allowError, _ = strconv.Atoi(v)
+			}
+
+			if k == 6 {
+				packageWeight, _ = strconv.Atoi(v)
+			}
+
+			if k == 7 {
+				price, _ = strconv.Atoi(v)
+			}
+
+			if k == 8 {
+				jumpWeight, _ = strconv.Atoi(v)
+			}
+
+			if k == 11 {
+				relayLocations, _ = strconv.Atoi(v)
+			}
+
+			if k == 13 {
+				backup1 = v
+			}
+
+			if k == 14 {
+				backup2 = v
+			}
+
+			if k == 15 {
+				backup3 = v
+			}
+		}
+
+		forageItem := &model.Forage{
+			Name:               row[0],
+			CategoryId:         int64(categoryId),
+			MaterialType:       0,
+			UniqueEncode:       row[2],
+			ForageSourceId:     operationPb.ForageSource_Kind(forageSourceId),
+			PlanTypeId:         0,
+			SmallMaterialScale: "",
+			AllowError:         int64(allowError),
+			PackageWeight:      int64(packageWeight),
+			Price:              int64(price),
+			JumpWeight:         int64(jumpWeight),
+			JumpDelay:          0,
+			ConfirmStart:       0,
+			RelayLocations:     int64(relayLocations),
+			Jmp:                0,
+			Backup1:            backup1,
+			Backup2:            backup2,
+			Backup3:            backup3,
+			IsShow:             operationPb.IsShow_OK,
+			IsDelete:           operationPb.IsShow_OK,
+			DataSource:         operationPb.DataSource_EXCEL_IMPORT,
+		}
+
+		forageList = append(forageList, forageItem)
+	}
+
+	if len(forageList) > 0 {
+		if err = s.DB.Create(forageList).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+	}
 
 	return nil
 }
 
-func (s *StoreEntry) ExportForage(ctx *gin.Context, req *operationPb.SearchForageListRequest) error {
-	res, err := s.SearchForageList(context.Background(), req)
+// ExcelExportForage 流式导出excel
+func (s *StoreEntry) ExcelExportForage(ctx context.Context, req *operationPb.SearchForageListRequest) (*bytes.Buffer, error) {
+	res, err := s.SearchForageList(ctx, req)
 	if err != nil {
-		return xerr.WithStack(err)
+		return nil, xerr.WithStack(err)
 	}
 	if len(res.List) <= 0 {
-		return nil
-	}
-	titleList := []string{
-		"a",
-		"b",
-		"c",
+		return nil, xerr.Custom("数据为空")
 	}
 
 	data := make([]interface{}, 0)
 	for _, v := range res.List {
 		data = append(data, v)
 	}
-	return s.ExcelClient.ExportExcelByStruct(titleList, data, "demo", "sheet1", ctx)
+
+	file := excelize.NewFile()
+	defer file.Close()
+
+	streamWriter, err := file.NewStreamWriter("Sheet1")
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	titles := []interface{}{"饲料名称", "饲料分类", "唯一编码", "饲料来源", "计划类型", "允许误差(kg)", "包装单位重量(kg)",
+		"单价", "跳转重量域(kg)", "跳转延迟", "确认开始", "继电器位置", "无上域", "备用字段01", "备用字段02", "备用字段03"}
+	if err = streamWriter.SetRow("A1", titles); err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	for i, item := range res.List {
+		cell, err := excelize.CoordinatesToCellName(1, i+2)
+		if err != nil {
+			zaplog.Error("excelize.CoordinatesToCellName", zap.Any("Err", err))
+			continue
+		}
+		row := make([]interface{}, 0)
+		row = append(row, item.Name, item.CategoryName, item.UniqueEncode, item.ForageSourceId, item.PlanTypeId,
+			item.AllowError, item.PackageWeight, float64(item.Price/100.00), item.JumpWeight, item.JumpDelay,
+			item.ConfirmStart, item.RelayLocations, item.Jmp, item.Backup1, item.Backup2, item.Backup3)
+
+		if err = streamWriter.SetRow(cell, row); err != nil {
+			return nil, xerr.WithStack(err)
+		}
+	}
+
+	if err = streamWriter.Flush(); err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	return file.WriteToBuffer()
+}
+
+// ExcelTemplateForage 导出模板
+func (s *StoreEntry) ExcelTemplateForage(ctx context.Context) (*bytes.Buffer, error) {
+	file := excelize.NewFile()
+	defer file.Close()
+
+	streamWriter, err := file.NewStreamWriter("Sheet1")
+	if err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	titles := []interface{}{"饲料名称", "饲料分类", "唯一编码", "饲料来源", "计划类型", "允许误差(kg)", "包装单位重量(kg)",
+		"单价", "跳转重量域(kg)", "跳转延迟", "确认开始", "继电器位置", "无上域", "备用字段01", "备用字段02", "备用字段03"}
+	if err = streamWriter.SetRow("A1", titles); err != nil {
+		return nil, xerr.WithStack(err)
+	}
+	if err = streamWriter.Flush(); err != nil {
+		return nil, xerr.WithStack(err)
+	}
+
+	return file.WriteToBuffer()
 }

+ 4 - 4
module/backend/system_permissions.go

@@ -86,7 +86,7 @@ func (s *StoreEntry) SystemPermissionsFormatPb(pastureList []*model.GroupPasture
 		for _, v := range pastureList {
 			systemUserMenuPermissions.Data.PastureList = append(systemUserMenuPermissions.Data.PastureList,
 				&operationPb.AddPastureRequest{
-					Id:   uint32(v.Id),
+					Id:   int32(v.Id),
 					Name: v.Name,
 				},
 			)
@@ -102,9 +102,9 @@ func (s *StoreEntry) SystemPermissionsFormatPb(pastureList []*model.GroupPasture
 				level[menu.Level] = make([]*operationPb.AddMenuRequest, 0)
 			}
 			level[menu.Level] = append(level[menu.Level], &operationPb.AddMenuRequest{
-				Id:              uint32(menu.Id),
+				Id:              int32(menu.Id),
 				Name:            menu.Name,
-				ParentId:        uint32(menu.ParentId),
+				ParentId:        int32(menu.ParentId),
 				MenuType:        menu.MenuType,
 				Title:           menu.Title,
 				Path:            menu.Path,
@@ -113,7 +113,7 @@ func (s *StoreEntry) SystemPermissionsFormatPb(pastureList []*model.GroupPasture
 				Icon:            menu.Icon,
 				Sort:            menu.Sort,
 				Redirect:        menu.Redirect,
-				CreatedAt:       uint32(menu.CreatedAt),
+				CreatedAt:       int32(menu.CreatedAt),
 				CreatedAtFormat: time.Unix(menu.CreatedAt, 0).Format(model.LayoutTime),
 				Level:           menu.Level,
 				Affix:           true,

+ 87 - 5
module/backend/system_service.go

@@ -84,7 +84,8 @@ func (s *StoreEntry) CreateSystemUser(ctx context.Context, req *operationPb.AddS
 		Phone:        req.Phone,
 		Password:     tool.Md5String(model.InitManagerPassword),
 		CreateUser:   req.CreateUser,
-		IsShow:       req.IsShow,
+		IsShow:       operationPb.IsShow_OK,
+		IsDelete:     operationPb.IsShow_OK,
 	}
 	systemUsers.SystemUserRoleFormat(req)
 
@@ -111,6 +112,10 @@ func (s *StoreEntry) SearchSystemUserList(ctx context.Context, req *operationPb.
 		pref.Where("is_show = ?", req.IsShow)
 	}
 
+	if req.CreatedStartTime > 0 && req.CreatedEndTime > 0 && req.CreatedStartTime <= req.CreatedEndTime {
+		pref.Where("created_at  BETWEEN  ? AND ?", req.CreatedStartTime, req.CreatedEndTime)
+	}
+
 	if err := pref.Order("id desc").Count(&count).Limit(int(req.Pagination.PageSize)).Offset(int(req.Pagination.PageOffset)).
 		Find(&systemUserList).Debug().Error; err != nil {
 		return nil, xerr.WithStack(err)
@@ -178,6 +183,43 @@ func (s *StoreEntry) DeleteSystemUser(ctx context.Context, userId int64) error {
 	return nil
 }
 
+// ResetPasswordSystemUser 重置系统用户密码
+func (s *StoreEntry) ResetPasswordSystemUser(ctx context.Context, userId int64) error {
+	systemUser := &model.SystemUser{
+		Id: userId,
+	}
+	if err := s.DB.First(systemUser).Error; err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return xerr.Custom("该用户不存在")
+		}
+		return xerr.WithStack(err)
+	}
+
+	if err := s.DB.Model(systemUser).Update("password", tool.Md5String(model.InitManagerPassword)).Error; err != nil {
+		return xerr.WithStack(err)
+	}
+	return nil
+}
+
+// DetailsSystemUser 系统用户详情
+func (s *StoreEntry) DetailsSystemUser(ctx context.Context, userId int64) (*operationPb.UserDetails, error) {
+	systemUser := &model.SystemUser{
+		Id: userId,
+	}
+	if err := s.DB.First(systemUser).Error; err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return nil, xerr.Custom("该用户不存在")
+		}
+		return nil, xerr.WithStack(err)
+	}
+
+	return &operationPb.UserDetails{
+		Code: http.StatusOK,
+		Msg:  "ok",
+		Data: systemUser.ToPb(),
+	}, nil
+}
+
 // IsShowSystemUser 用户是否启用
 func (s *StoreEntry) IsShowSystemUser(ctx context.Context, req *operationPb.IsShowSystemUserRequest) error {
 	systemUser := &model.SystemUser{
@@ -304,10 +346,50 @@ func (s *StoreEntry) EditSystemRole(ctx context.Context, req *operationPb.AddRol
 		return xerr.WithStack(err)
 	}
 
-	updateSystemRole := model.NewSystemRole(req)
-	if err := s.DB.Omit("is_show").
-		Where("id = ?", role.Id).
-		Updates(updateSystemRole).Error; err != nil {
+	if err := s.DB.Transaction(func(tx *gorm.DB) error {
+		updateSystemRole := model.NewSystemRole(req)
+		if err := tx.Omit("is_show").
+			Where("id = ?", role.Id).
+			Updates(updateSystemRole).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+
+		// 更新牧场权限关系表
+		pastureIds := req.PastureId
+		if err := tx.Model(new(model.SystemGroupPasturePermissions)).
+			Where("role_id = ?", req.Id).Update("is_show", operationPb.IsShow_NO).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+
+		newSystemGroupPasturePermissions := model.NewSystemGroupPasturePermissions(int64(req.Id), pastureIds)
+		if err := tx.Create(newSystemGroupPasturePermissions).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+
+		// 更新菜单权限关系表
+		menuIds := req.MenuId
+		if err := tx.Model(new(model.SystemMenuPermissions)).
+			Where("role_id = ?", req.Id).Update("is_show", operationPb.IsShow_NO).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+
+		newSystemMenuPermissions := model.NewSystemMenuPermissions(int64(req.Id), menuIds)
+		if err := tx.Create(newSystemMenuPermissions).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+		// 更新移动端权限关系表
+		mobileIds := req.MobileId
+		if err := tx.Model(new(model.SystemMobilePermissions)).
+			Where("role_id = ?", req.Id).Update("is_show", operationPb.IsShow_NO).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+
+		newSystemMobilePermissions := model.NewSystemMobilePermissions(int64(req.Id), mobileIds)
+		if err := tx.Create(newSystemMobilePermissions).Error; err != nil {
+			return xerr.WithStack(err)
+		}
+		return nil
+	}); err != nil {
 		return xerr.WithStack(err)
 	}
 

+ 122 - 12
proto/go/backend/operation/enum.pb.go

@@ -335,6 +335,58 @@ func (ForagePlanType_Kind) EnumDescriptor() ([]byte, []int) {
 	return file_backend_operation_enum_proto_rawDescGZIP(), []int{5, 0}
 }
 
+type DataSource_Kind int32
+
+const (
+	DataSource_INVALID        DataSource_Kind = 0 // 无
+	DataSource_BACKGROUND_ADD DataSource_Kind = 1 // 后台手动添加
+	DataSource_EXCEL_IMPORT   DataSource_Kind = 2 // excel报表导入
+	DataSource_FROM_PASTURE   DataSource_Kind = 3 // 来自牧场
+)
+
+// Enum value maps for DataSource_Kind.
+var (
+	DataSource_Kind_name = map[int32]string{
+		0: "INVALID",
+		1: "BACKGROUND_ADD",
+		2: "EXCEL_IMPORT",
+		3: "FROM_PASTURE",
+	}
+	DataSource_Kind_value = map[string]int32{
+		"INVALID":        0,
+		"BACKGROUND_ADD": 1,
+		"EXCEL_IMPORT":   2,
+		"FROM_PASTURE":   3,
+	}
+)
+
+func (x DataSource_Kind) Enum() *DataSource_Kind {
+	p := new(DataSource_Kind)
+	*p = x
+	return p
+}
+
+func (x DataSource_Kind) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (DataSource_Kind) Descriptor() protoreflect.EnumDescriptor {
+	return file_backend_operation_enum_proto_enumTypes[6].Descriptor()
+}
+
+func (DataSource_Kind) Type() protoreflect.EnumType {
+	return &file_backend_operation_enum_proto_enumTypes[6]
+}
+
+func (x DataSource_Kind) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use DataSource_Kind.Descriptor instead.
+func (DataSource_Kind) EnumDescriptor() ([]byte, []int) {
+	return file_backend_operation_enum_proto_rawDescGZIP(), []int{6, 0}
+}
+
 // 字段类型
 type IsShow struct {
 	state         protoimpl.MessageState
@@ -568,6 +620,44 @@ func (*ForagePlanType) Descriptor() ([]byte, []int) {
 	return file_backend_operation_enum_proto_rawDescGZIP(), []int{5}
 }
 
+type DataSource struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+}
+
+func (x *DataSource) Reset() {
+	*x = DataSource{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_backend_operation_enum_proto_msgTypes[6]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *DataSource) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DataSource) ProtoMessage() {}
+
+func (x *DataSource) ProtoReflect() protoreflect.Message {
+	mi := &file_backend_operation_enum_proto_msgTypes[6]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use DataSource.ProtoReflect.Descriptor instead.
+func (*DataSource) Descriptor() ([]byte, []int) {
+	return file_backend_operation_enum_proto_rawDescGZIP(), []int{6}
+}
+
 var File_backend_operation_enum_proto protoreflect.FileDescriptor
 
 var file_backend_operation_enum_proto_rawDesc = []byte{
@@ -607,8 +697,14 @@ var file_backend_operation_enum_proto_rawDesc = []byte{
 	0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44,
 	0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x4b, 0x4c, 0x49, 0x46, 0x54, 0x10, 0x01,
 	0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4f, 0x4e, 0x43, 0x45, 0x4e, 0x54, 0x52, 0x41, 0x54, 0x45, 0x10,
-	0x02, 0x42, 0x0f, 0x5a, 0x0d, 0x2e, 0x3b, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-	0x50, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x02, 0x22, 0x59, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22,
+	0x4b, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c,
+	0x49, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x42, 0x41, 0x43, 0x4b, 0x47, 0x52, 0x4f, 0x55,
+	0x4e, 0x44, 0x5f, 0x41, 0x44, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x45, 0x58, 0x43, 0x45,
+	0x4c, 0x5f, 0x49, 0x4d, 0x50, 0x4f, 0x52, 0x54, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x52,
+	0x4f, 0x4d, 0x5f, 0x50, 0x41, 0x53, 0x54, 0x55, 0x52, 0x45, 0x10, 0x03, 0x42, 0x0f, 0x5a, 0x0d,
+	0x2e, 0x3b, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x62, 0x62, 0x06, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -623,8 +719,8 @@ func file_backend_operation_enum_proto_rawDescGZIP() []byte {
 	return file_backend_operation_enum_proto_rawDescData
 }
 
-var file_backend_operation_enum_proto_enumTypes = make([]protoimpl.EnumInfo, 6)
-var file_backend_operation_enum_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
+var file_backend_operation_enum_proto_enumTypes = make([]protoimpl.EnumInfo, 7)
+var file_backend_operation_enum_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
 var file_backend_operation_enum_proto_goTypes = []interface{}{
 	(IsShow_Kind)(0),               // 0: backend.operation.IsShow.Kind
 	(CattleCategoryParent_Kind)(0), // 1: backend.operation.CattleCategoryParent.Kind
@@ -632,12 +728,14 @@ var file_backend_operation_enum_proto_goTypes = []interface{}{
 	(ForageSource_Kind)(0),         // 3: backend.operation.ForageSource.Kind
 	(JumpDelaType_Kind)(0),         // 4: backend.operation.JumpDelaType.Kind
 	(ForagePlanType_Kind)(0),       // 5: backend.operation.ForagePlanType.Kind
-	(*IsShow)(nil),                 // 6: backend.operation.IsShow
-	(*CattleCategoryParent)(nil),   // 7: backend.operation.CattleCategoryParent
-	(*ForageCategoryParent)(nil),   // 8: backend.operation.ForageCategoryParent
-	(*ForageSource)(nil),           // 9: backend.operation.ForageSource
-	(*JumpDelaType)(nil),           // 10: backend.operation.JumpDelaType
-	(*ForagePlanType)(nil),         // 11: backend.operation.ForagePlanType
+	(DataSource_Kind)(0),           // 6: backend.operation.DataSource.Kind
+	(*IsShow)(nil),                 // 7: backend.operation.IsShow
+	(*CattleCategoryParent)(nil),   // 8: backend.operation.CattleCategoryParent
+	(*ForageCategoryParent)(nil),   // 9: backend.operation.ForageCategoryParent
+	(*ForageSource)(nil),           // 10: backend.operation.ForageSource
+	(*JumpDelaType)(nil),           // 11: backend.operation.JumpDelaType
+	(*ForagePlanType)(nil),         // 12: backend.operation.ForagePlanType
+	(*DataSource)(nil),             // 13: backend.operation.DataSource
 }
 var file_backend_operation_enum_proto_depIdxs = []int32{
 	0, // [0:0] is the sub-list for method output_type
@@ -725,14 +823,26 @@ func file_backend_operation_enum_proto_init() {
 				return nil
 			}
 		}
+		file_backend_operation_enum_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*DataSource); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
 	}
 	type x struct{}
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_backend_operation_enum_proto_rawDesc,
-			NumEnums:      6,
-			NumMessages:   6,
+			NumEnums:      7,
+			NumMessages:   7,
 			NumExtensions: 0,
 			NumServices:   0,
 		},

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 387 - 439
proto/go/backend/operation/pasture.pb.go


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 330 - 247
proto/go/backend/operation/system.pb.go


+ 0 - 177
service/excel/excel.go

@@ -1,177 +0,0 @@
-package excel
-
-import (
-	"fmt"
-	"net/url"
-	"reflect"
-	"strconv"
-
-	"github.com/gin-gonic/gin"
-	"github.com/xuri/excelize/v2"
-)
-
-type ExcelServer struct {
-	File      *excelize.File
-	SheetName string  // 可定义默认sheet名称
-	Height    float64 // 默认行高度
-}
-
-// ExportToPath 导出基本的表格
-func (l *ExcelServer) ExportToPath(params []map[string]string, data []map[string]interface{}, path string) (string, error) {
-	l.Export(params, data)
-	name := createFileName()
-	filePath := path + "/" + name
-	err := l.File.SaveAs(filePath)
-	return filePath, err
-}
-
-// ExportToWeb 导出到浏览器。此处使用的gin框架 其他框架可自行修改ctx
-func (l *ExcelServer) ExportToWeb(params []map[string]string, data []map[string]interface{}, c *gin.Context) {
-	l.Export(params, data)
-	buffer, _ := l.File.WriteToBuffer()
-	//设置文件类型
-	c.Header("Content-Type", "application/vnd.ms-excel;charset=utf8")
-	//设置文件名称
-	c.Header("Content-Disposition", "attachment; filename="+url.QueryEscape(createFileName()))
-	_, _ = c.Writer.Write(buffer.Bytes())
-}
-
-//设置首行
-func (l *ExcelServer) writeTop(params []map[string]string) {
-	topStyle, _ := l.File.NewStyle(&excelize.Style{
-		Font: &excelize.Font{Bold: true},
-		Alignment: &excelize.Alignment{
-			Horizontal: "center",
-			Vertical:   "center",
-		},
-		Protection:    nil,
-		NumFmt:        0,
-		DecimalPlaces: 0,
-		CustomNumFmt:  nil,
-		Lang:          "",
-		NegRed:        false,
-	})
-	var word = 'A'
-	//首行写入
-	for _, conf := range params {
-		title := conf["title"]
-		width, _ := strconv.ParseFloat(conf["width"], 64)
-		line := fmt.Sprintf("%c1", word)
-		//设置标题
-		_ = l.File.SetCellValue(l.SheetName, line, title)
-		//列宽
-		_ = l.File.SetColWidth(l.SheetName, fmt.Sprintf("%c", word), fmt.Sprintf("%c", word), width)
-		//设置样式
-		_ = l.File.SetCellStyle(l.SheetName, line, line, topStyle)
-		word++
-	}
-}
-
-//写入数据
-func (l *ExcelServer) writeData(params []map[string]string, data []map[string]interface{}) {
-	lineStyle, _ := l.File.NewStyle(&excelize.Style{Alignment: &excelize.Alignment{
-		Horizontal: "center",
-		Vertical:   "center",
-	}})
-	//数据写入
-	var j = 2 //数据开始行数
-	for i, val := range data {
-		//设置行高
-		_ = l.File.SetRowHeight(l.SheetName, i+1, l.Height)
-		//逐列写入
-		var word = 'A'
-		for _, conf := range params {
-			valKey := conf["key"]
-			line := fmt.Sprintf("%c%v", word, j)
-			isNum := conf["is_num"]
-
-			//设置值
-			if isNum != "0" {
-				valNum := fmt.Sprintf("'%v", val[valKey])
-				_ = l.File.SetCellValue(l.SheetName, line, valNum)
-			} else {
-				_ = l.File.SetCellValue(l.SheetName, line, val[valKey])
-			}
-
-			//设置样式
-			_ = l.File.SetCellStyle(l.SheetName, line, line, lineStyle)
-			word++
-		}
-		j++
-	}
-	//设置行高 尾行
-	_ = l.File.SetRowHeight(l.SheetName, len(data)+1, l.Height)
-}
-
-func (l *ExcelServer) Export(params []map[string]string, data []map[string]interface{}) {
-	l.writeTop(params)
-	l.writeData(params, data)
-}
-
-// ExportExcelByStruct excel导出(数据源为Struct) []interface{}
-func (l *ExcelServer) ExportExcelByStruct(titleList []string, data []interface{}, fileName string, sheetName string, c *gin.Context) error {
-	l.File.SetSheetName("Sheet1", sheetName)
-	header := make([]string, 0)
-	for _, v := range titleList {
-		header = append(header, v)
-	}
-	rowStyleID, _ := l.File.NewStyle(&excelize.Style{
-		Font: &excelize.Font{
-			Family: "arial",
-			Size:   13,
-			Color:  "#666666",
-		},
-		Alignment: &excelize.Alignment{
-			Horizontal: "center",
-			Vertical:   "center",
-		},
-	})
-	_ = l.File.SetSheetRow(sheetName, "A1", &header)
-	_ = l.File.SetRowHeight("Sheet1", 1, 30)
-	length := len(titleList)
-	headStyle := Letter(length)
-	var lastRow string
-	var widthRow string
-	for k, v := range headStyle {
-		if k == length-1 {
-			lastRow = fmt.Sprintf("%s1", v)
-			widthRow = v
-		}
-	}
-	if err := l.File.SetColWidth(sheetName, "A", widthRow, 30); err != nil {
-		fmt.Print("错误--", err.Error())
-	}
-	rowNum := 1
-	for _, v := range data {
-		t := reflect.TypeOf(v)
-		fmt.Print("--ttt--", t.NumField())
-		value := reflect.ValueOf(v)
-		row := make([]interface {
-		}, 0)
-		for l := 0; l < t.NumField(); l++ {
-			val := value.Field(l).Interface()
-			row = append(row, val)
-		}
-		rowNum++
-		err := l.File.SetSheetRow(sheetName, "A"+strconv.Itoa(rowNum), &row)
-		_ = l.File.SetCellStyle(sheetName, fmt.Sprintf("A%d", rowNum), fmt.Sprintf("%s", lastRow), rowStyleID)
-		if err != nil {
-			return err
-		}
-	}
-	disposition := fmt.Sprintf("attachment; filename=%s.xlsx", url.QueryEscape(fileName))
-	c.Writer.Header().Set("Content-Type", "application/octet-stream")
-	c.Writer.Header().Set("Content-Disposition", disposition)
-	c.Writer.Header().Set("Content-Transfer-Encoding", "binary")
-	c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Disposition")
-	return l.File.Write(c.Writer)
-}
-
-// Letter 遍历a-z
-func Letter(length int) []string {
-	var str []string
-	for i := 0; i < length; i++ {
-		str = append(str, string(rune('A'+i)))
-	}
-	return str
-}

+ 0 - 84
service/excel/interface.go

@@ -4,7 +4,6 @@ import (
 	"fmt"
 	"kpt-tmr-group/config"
 	"kpt-tmr-group/model"
-	"kpt-tmr-group/pkg/di"
 	"math/rand"
 	"time"
 
@@ -21,12 +20,6 @@ type SheetService interface {
 	Export(params []map[string]string, data []map[string]interface{})
 }
 
-var Module = di.Provide(NewMyExcel)
-
-func NewMyExcel(cfg *config.AppConfig) *ExcelServer {
-	return &ExcelServer{File: createFile(cfg), SheetName: cfg.ExcelSetting.SheetName}
-}
-
 func createFile(cfg *config.AppConfig) *excelize.File {
 	f := excelize.NewFile()
 	// 创建一个默认工作表
@@ -41,80 +34,3 @@ func createFileName() string {
 	rand.Seed(time.Now().UnixNano())
 	return fmt.Sprintf("excle-%v-%v.xlsx", name, rand.Int63n(time.Now().Unix()))
 }
-
-/*import (
-"go-excel/app/excelize"
-"go-excel/app/model"
-config "go-excel/common"
-"github.com/gin-gonic/gin"
-)
-
-
-
-//获取所有用户数据-excel
-func GetAllUserExportToWeb(ctx *gin.Context) {
-	var users []model.TUser
-	db := config.GetDB()
-	db.Find(&users)
-
-	//定义首行标题
-	dataKey := make([]map[string]string, 0)
-	dataKey = append(dataKey, map[string]string{
-		"key":    "id",
-		"title":  "索引",
-		"width":  "20",
-		"is_num": "0",
-	})
-	dataKey = append(dataKey, map[string]string{
-		"key":    "username",
-		"title":  "用户名",
-		"width":  "20",
-		"is_num": "0",
-	})
-	dataKey = append(dataKey, map[string]string{
-		"key":    "remark",
-		"title":  "备注",
-		"width":  "20",
-		"is_num": "0",
-	})
-
-	//填充数据
-	data := make([]map[string]interface{}, 0)
-	if len(users) > 0 {
-		for _, v := range users {
-			data = append(data, map[string]interface{}{
-				"id":       v.ID,
-				"username": v.Username,
-				"remark":   v.Remark,
-			})
-		}
-	}
-	ex := excelize.NewMyExcel()
-
-	// ex.ExportToWeb(dataKey, data, ctx)
-
-	//保存到D盘
-	ex.ExportToPath(dataKey, data, "D:/")
-}
-
-//excel 导出
-func GetUserExcelByMap(ctx *gin.Context) {
-	var users []model.TUser
-	db := config.GetDB()
-	db.Find(&users)
-
-	titles := []string{"ID", "用户名", "备注"}
-
-	ex := excelize.NewMyExcel()
-
-	var datas []interface{}
-	for _, v := range users {
-		//这里最好新建一个struct 和titles一致,不然users里面的多余的字段也会写进去
-		datas = append(datas, model.TUser{
-			ID:       v.ID,
-			Username: v.Username,
-			Remark:   v.Remark,
-		})
-	}
-	ex.ExportExcelByStruct(titles, datas, "用户数据", "用户", ctx)
-}*/

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä