From 3f5d062ee80c8cf5e044f033090eff66da93d843 Mon Sep 17 00:00:00 2001 From: suguo <25950955@qq.com> Date: Wed, 18 Mar 2026 17:18:06 +0800 Subject: [PATCH] init --- gin/router-gin.go | 3 +- handler/option-handler.go | 19 ++++++ handler/org-handler.go | 56 +++++------------ model/artifact-model.go | 31 +++++++++ model/option-model.go | 8 +++ model/org-model.go | 23 ++++--- mysql/option-mysql.go | 47 ++++++++++++++ mysql/tables-mysql.go | 11 +++- service/bootstrap-service.go | 39 ++++++++++-- service/option-service.go | 19 ++++++ service/org-service.go | 118 ++++++++++++++++++++++++++--------- 11 files changed, 287 insertions(+), 87 deletions(-) create mode 100644 handler/option-handler.go create mode 100644 model/artifact-model.go create mode 100644 model/option-model.go create mode 100644 mysql/option-mysql.go create mode 100644 service/option-service.go diff --git a/gin/router-gin.go b/gin/router-gin.go index 7069ee1..2d85fc8 100644 --- a/gin/router-gin.go +++ b/gin/router-gin.go @@ -19,7 +19,7 @@ func routerSetup(router *gin.Engine) { protected.GET("/orgs", handler.OrgList) protected.POST("/orgs", handler.OrgCreate) - protected.GET("/orgs/:id", handler.OrgGet) + protected.GET("/orgs/:id", handler.OrgDetail) protected.PUT("/orgs/:id", handler.OrgUpdate) protected.DELETE("/orgs/:id", handler.OrgDelete) @@ -54,4 +54,5 @@ func routerSetup(router *gin.Engine) { protected.DELETE("/devices/:id", handler.DeviceDelete) protected.GET("/menus", handler.MenuList) + protected.GET("/options", handler.OptionMap) } diff --git a/handler/option-handler.go b/handler/option-handler.go new file mode 100644 index 0000000..8bdd60e --- /dev/null +++ b/handler/option-handler.go @@ -0,0 +1,19 @@ +package handler + +import ( + "net/http" + + "github.com/gin-gonic/gin" + "myschools.me/heritage/heritage-api/service" +) + +// 系统选项map +func OptionMap(c *gin.Context) { + name := c.Query("name") + optionMap, err := service.OptionMap(&name) + if err != nil { + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"data": "查询失败"}) + return + } + c.JSON(http.StatusOK, gin.H{"data": optionMap}) +} diff --git a/handler/org-handler.go b/handler/org-handler.go index 9952c96..ede7f20 100644 --- a/handler/org-handler.go +++ b/handler/org-handler.go @@ -7,52 +7,28 @@ import ( "myschools.me/heritage/heritage-api/service" ) -type OrgCreateRequest struct { - ParentID string `json:"parentId"` - Name string `json:"name"` - Enabled *bool `json:"enabled"` - Sort *int `json:"sort"` - Remark string `json:"remark"` -} - -type OrgUpdateRequest struct { - ParentID *string `json:"parentId"` - Name *string `json:"name"` - Enabled *bool `json:"enabled"` - Sort *int `json:"sort"` - Remark *string `json:"remark"` -} - func OrgCreate(c *gin.Context) { - var req OrgCreateRequest + var req service.OrgCreateRequest if err := c.ShouldBindJSON(&req); err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"data": "参数错误"}) return } - enabled := true - if req.Enabled != nil { - enabled = *req.Enabled - } - sort := 0 - if req.Sort != nil { - sort = *req.Sort - } - o, err := service.OrgCreateOrg(req.ParentID, req.Name, enabled, sort, req.Remark) + o, err := service.OrgCreate(req) if err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"data": err.Error()}) return } - c.JSON(http.StatusOK, gin.H{"org": o}) + c.JSON(http.StatusOK, service.OrgResponse{Org: o}) } func OrgUpdate(c *gin.Context) { id := c.Param("id") - var req OrgUpdateRequest + var req service.OrgUpdateRequest if err := c.ShouldBindJSON(&req); err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"data": "参数错误"}) return } - o, err := service.OrgUpdateOrg(id, req.ParentID, req.Name, req.Enabled, req.Sort, req.Remark) + o, err := service.OrgUpdate(id, req) if err != nil { if err == service.ErrNotFound { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"data": "不存在"}) @@ -61,12 +37,12 @@ func OrgUpdate(c *gin.Context) { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"data": err.Error()}) return } - c.JSON(http.StatusOK, gin.H{"org": o}) + c.JSON(http.StatusOK, service.OrgResponse{Org: o}) } func OrgDelete(c *gin.Context) { id := c.Param("id") - if err := service.OrgDeleteOrg(id); err != nil { + if err := service.OrgDelete(id); err != nil { if err == service.ErrNotFound { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"data": "不存在"}) return @@ -77,9 +53,9 @@ func OrgDelete(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"data": "ok"}) } -func OrgGet(c *gin.Context) { +func OrgDetail(c *gin.Context) { id := c.Param("id") - o, err := service.OrgGetOrg(id) + o, err := service.OrgDetail(id) if err != nil { if err == service.ErrNotFound { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"data": "不存在"}) @@ -88,7 +64,7 @@ func OrgGet(c *gin.Context) { c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"data": "查询失败"}) return } - c.JSON(http.StatusOK, gin.H{"org": o}) + c.JSON(http.StatusOK, service.OrgResponse{Org: o}) } func OrgList(c *gin.Context) { @@ -98,15 +74,15 @@ func OrgList(c *gin.Context) { if parentID != "" { pid = &parentID } - items, total, err := service.OrgListOrgs(pid, page, size) + items, total, err := service.OrgPage(pid, page, size) if err != nil { c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"data": "查询失败"}) return } - c.JSON(http.StatusOK, gin.H{ - "items": items, - "total": total, - "page": page, - "size": size, + c.JSON(http.StatusOK, service.OrgListResponse{ + Items: items, + Total: total, + Page: page, + Size: size, }) } diff --git a/model/artifact-model.go b/model/artifact-model.go new file mode 100644 index 0000000..ff1a1d8 --- /dev/null +++ b/model/artifact-model.go @@ -0,0 +1,31 @@ +package model + +import "time" + +// 文物表 +type Artifact struct { + ID string `json:"id" gorm:"type:varchar(32);primaryKey"` + Code string `json:"code" gorm:"type:varchar(64);not null;uniqueIndex;comment:'文物编码'"` + Name string `json:"name" gorm:"type:varchar(128);not null;index"` + OrgID string `json:"orgId" gorm:"type:varchar(32);not null;index"` + Category string `json:"category" gorm:"type:varchar(50);default:'';comment:'文物类别'"` + Material string `json:"material" gorm:"type:varchar(50);default:'';comment:'材质'"` + Period string `json:"period" gorm:"type:varchar(50);default:'';comment:'年代'"` + Description string `json:"description" gorm:"type:text;comment:'文物描述'"` + CurrentUser string `json:"currentUser" gorm:"type:varchar(32);default:'';comment:'当前所属用户'"` + Remark string `json:"remark" gorm:"type:varchar(255);comment:'文物备注'"` + Province string `json:"province" gorm:"type:varchar(50);default:'';comment:'省'"` + City string `json:"city" gorm:"type:varchar(50);default:'';comment:'市'"` + District string `json:"district" gorm:"type:varchar(50);default:'';comment:'区/县'"` + Address string `json:"address" gorm:"type:varchar(255);default:'';comment:'详细地址'"` + StatisticsPeriod string `json:"statisticsPeriod" gorm:"type:varchar(50);default:'';comment:'统计年代'"` + LevelType string `json:"levelType" gorm:"type:varchar(50);default:'';comment:'层级类型'"` + BuildingType string `json:"buildingType" gorm:"type:varchar(50);default:'';comment:'建筑类型'"` + CurrentOrg string `json:"currentOrg" gorm:"type:varchar(32);default:'';comment:'当前所属机构'"` + Introduction string `json:"introduction" gorm:"type:text;comment:'简介'"` + Images string `json:"images" gorm:"type:varchar(255);default:'';comment:'图片'"` + Icon string `json:"icon" gorm:"type:varchar(255);default:'';comment:'图标'"` + Sort int `json:"sort" gorm:"type:int;default:0;comment:'排序'"` + CreatedAt time.Time `json:"createdAt" gorm:"autoCreateTime"` + UpdatedAt time.Time `json:"updatedAt" gorm:"autoUpdateTime"` +} diff --git a/model/option-model.go b/model/option-model.go new file mode 100644 index 0000000..c938a00 --- /dev/null +++ b/model/option-model.go @@ -0,0 +1,8 @@ +package model + +// 系统选项表 +type Option struct { + ID uint `json:"id" gorm:"primaryKey"` + OptionName string `json:"optionName" gorm:"type:varchar(10);not null;index;comment:单位选项,level-保护单位级别,type-保护单位类别,batch-公布批次"` + OptionValue string `json:"optionValue" gorm:"type:varchar(50);not null;"` +} diff --git a/model/org-model.go b/model/org-model.go index b83add4..2655c81 100644 --- a/model/org-model.go +++ b/model/org-model.go @@ -2,14 +2,19 @@ package model import "time" +// 保护单位组织结构表 type Org struct { - ID string `json:"id" gorm:"type:varchar(32);primaryKey"` - ParentID string `json:"parentId" gorm:"type:varchar(32);index"` - Name string `json:"name" gorm:"type:varchar(128);not null;index"` - Enabled bool `json:"enabled" gorm:"not null;default:true;index"` - Sort int `json:"sort" gorm:"not null;default:0"` - Remark string `json:"remark" gorm:"type:varchar(255);default:''"` - Deleted bool `json:"deleted" gorm:"not null;default:false;index"` - CreatedAt time.Time `json:"createdAt" gorm:"autoCreateTime"` - UpdatedAt time.Time `json:"updatedAt" gorm:"autoUpdateTime"` + ID string `json:"id" gorm:"type:varchar(32);primaryKey"` + Code string `json:"code" gorm:"type:varchar(64);not null;uniqueIndex;comment:'组织编码'"` + ParentID string `json:"parentId" gorm:"type:varchar(32);index"` + Name string `json:"name" gorm:"type:varchar(128);not null;index"` + OrgType string `json:"orgType" gorm:"type:varchar(10);not null;comment:'组织类型'"` + ProtectionLevel string `json:"protectionLevel" gorm:"type:varchar(10);default:'';comment:'保护单位级别'"` + ProtectionType string `json:"protectionType" gorm:"type:varchar(10);default:'';comment:'保护单位类别'"` + AnnouncementBatch string `json:"announcementBatch" gorm:"type:varchar(50);default:'';comment:'公布批次'"` + AdminRegion string `json:"adminRegion" gorm:"type:varchar(100);default:'';comment:'行政区域'"` + Introduction string `json:"introduction" gorm:"type:text;comment:'简介'"` + Remark string `json:"remark" gorm:"type:varchar(255);default:'';comment:'组织备注'"` + CreatedAt time.Time `json:"createdAt" gorm:"autoCreateTime"` + UpdatedAt time.Time `json:"updatedAt" gorm:"autoUpdateTime"` } diff --git a/mysql/option-mysql.go b/mysql/option-mysql.go new file mode 100644 index 0000000..05ca3dc --- /dev/null +++ b/mysql/option-mysql.go @@ -0,0 +1,47 @@ +package mysql + +import ( + "errors" + + "gorm.io/gorm" + "myschools.me/heritage/heritage-api/model" +) + +// 获取选项 +func OptionPluck(name *string) ([]string, error) { + db, err := newDB() + if err != nil { + return nil, err + } + + var options []string + if err := db.Where("option_name=?", *name).Pluck("option_value", &options).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, nil + } + } + return options, nil +} + +// 获取选项数量 +func OptionCount() (*int64, error) { + db, err := newDB() + if err != nil { + return nil, err + } + + var count int64 + if err := db.Model(&model.Option{}).Count(&count).Error; err != nil { + return nil, err + } + return &count, nil +} + +// OptionCreateBatch 批量创建选项 +func OptionCreateBatch(options []model.Option) error { + db, err := newDB() + if err != nil { + return err + } + return db.Create(&options).Error +} diff --git a/mysql/tables-mysql.go b/mysql/tables-mysql.go index 8222d84..fc6405e 100644 --- a/mysql/tables-mysql.go +++ b/mysql/tables-mysql.go @@ -9,18 +9,27 @@ func init() { if err != nil { panic(err) } + //系统相关表 if err := db.AutoMigrate( &model.Role{}, &model.Permission{}, &model.User{}, &model.Org{}, + &model.Menu{}, + &model.Option{}, + ); err != nil { + panic(err) + } + + //业务相关表 + if err := db.AutoMigrate( &model.Project{}, &model.Task{}, &model.Point{}, &model.DataRecord{}, &model.Device{}, &model.DeviceIngestData{}, - &model.Menu{}, + &model.Artifact{}, ); err != nil { panic(err) } diff --git a/service/bootstrap-service.go b/service/bootstrap-service.go index bb62e00..3cac1dc 100644 --- a/service/bootstrap-service.go +++ b/service/bootstrap-service.go @@ -19,12 +19,12 @@ func Bootstrap() { menus := []model.Menu{ {ID: 1, Name: "首页", Icon: "home", Path: "/dashboard", Sort: 1, PermissionCode: "dashboard"}, {ID: 2, Name: "系统管理", Icon: "setting", Path: "/system", Sort: 2, PermissionCode: "system"}, - {ID: 3, ParentID: 2, Name: "组织机构", Icon: "team", Path: "/system/org", Sort: 1, PermissionCode: "org:list"}, - {ID: 4, ParentID: 2, Name: "项目管理", Icon: "project", Path: "/system/project", Sort: 2, PermissionCode: "project:list"}, - {ID: 5, ParentID: 2, Name: "任务管理", Icon: "profile", Path: "/system/task", Sort: 3, PermissionCode: "task:list"}, - {ID: 6, ParentID: 2, Name: "监测点位", Icon: "environment", Path: "/system/point", Sort: 4, PermissionCode: "point:list"}, - {ID: 7, ParentID: 2, Name: "数据记录", Icon: "database", Path: "/system/data", Sort: 5, PermissionCode: "data:list"}, - {ID: 8, ParentID: 2, Name: "设备管理", Icon: "cluster", Path: "/system/device", Sort: 6, PermissionCode: "device:list"}, + {ID: 3, Name: "组织机构", Icon: "team", Path: "/org", Sort: 1, PermissionCode: "org:list"}, + {ID: 4, Name: "项目管理", Icon: "project", Path: "/project", Sort: 2, PermissionCode: "project:list"}, + {ID: 5, Name: "任务管理", Icon: "profile", Path: "/task", Sort: 3, PermissionCode: "task:list"}, + {ID: 6, Name: "监测点位", Icon: "environment", Path: "/point", Sort: 4, PermissionCode: "point:list"}, + {ID: 7, Name: "数据记录", Icon: "database", Path: "/data", Sort: 5, PermissionCode: "data:list"}, + {ID: 8, Name: "设备管理", Icon: "cluster", Path: "/device", Sort: 6, PermissionCode: "device:list"}, } if err := mysql.MenuCreateBatch(menus); err != nil { logrus.WithFields(logrus.Fields{ @@ -116,4 +116,31 @@ func Bootstrap() { panic(err) } } + + // 初始化组织选项 + optionCount, err := mysql.OptionCount() + if err != nil { + logrus.WithFields(logrus.Fields{ + "func": "Bootstrap", + }).Warnf("mysql.OptionCount: %v", err) + panic(err) + } + if *optionCount == 0 { + orgOptions := []model.Option{ + {OptionName: "level", OptionValue: "国家级"}, + {OptionName: "level", OptionValue: "省级"}, + {OptionName: "level", OptionValue: "市级"}, + {OptionName: "type", OptionValue: "古建筑"}, + {OptionName: "type", OptionValue: "古遗址"}, + {OptionName: "type", OptionValue: "古墓葬"}, + {OptionName: "batch", OptionValue: "第一批"}, + {OptionName: "batch", OptionValue: "第二批"}, + } + if err := mysql.OptionCreateBatch(orgOptions); err != nil { + logrus.WithFields(logrus.Fields{ + "func": "Bootstrap", + }).Warnf("mysql.OptionCreateBatch: %v", err) + panic(err) + } + } } diff --git a/service/option-service.go b/service/option-service.go new file mode 100644 index 0000000..5b54cb1 --- /dev/null +++ b/service/option-service.go @@ -0,0 +1,19 @@ +package service + +import ( + "github.com/sirupsen/logrus" + "myschools.me/heritage/heritage-api/mysql" +) + +// 获取组织选项映射,用于前端下拉列表 +func OptionMap(name *string) ([]string, error) { + options, err := mysql.OptionPluck(name) + if err != nil { + logrus.WithFields(logrus.Fields{ + "func": "OptionMap", + }).Warnf("mysql.OptionPluck: %v", err) + return nil, err + } + + return options, nil +} diff --git a/service/org-service.go b/service/org-service.go index f932ca9..e906414 100644 --- a/service/org-service.go +++ b/service/org-service.go @@ -11,29 +11,78 @@ import ( var ErrNotFound = errors.New("not found") -func OrgCreateOrg(parentID, name string, enabled bool, sort int, remark string) (*model.Org, error) { - name = strings.TrimSpace(name) +// OrgCreateRequest 创建组织请求结构 +type OrgCreateRequest struct { + ParentID string `json:"parentId"` + Name string `json:"name"` + Enabled *bool `json:"enabled"` + Sort *int `json:"sort"` + Remark string `json:"remark"` + ProtectionLevel string `json:"protectionLevel"` + ProtectionType string `json:"protectionType"` + AnnouncementBatch string `json:"announcementBatch"` + AdminRegion string `json:"adminRegion"` + CurrentOrg string `json:"currentOrg"` + CurrentUser string `json:"currentUser"` + Introduction string `json:"introduction"` +} + +// OrgUpdateRequest 更新组织请求结构 +type OrgUpdateRequest struct { + ParentID *string `json:"parentId"` + Name *string `json:"name"` + Enabled *bool `json:"enabled"` + Sort *int `json:"sort"` + Remark *string `json:"remark"` + ProtectionLevel *string `json:"protectionLevel"` + ProtectionType *string `json:"protectionType"` + AnnouncementBatch *string `json:"announcementBatch"` + AdminRegion *string `json:"adminRegion"` + CurrentOrg *string `json:"currentOrg"` + CurrentUser *string `json:"currentUser"` + Introduction *string `json:"introduction"` +} + +// OrgResponse 组织响应结构 +type OrgResponse struct { + Org *model.Org `json:"org"` +} + +// OrgListResponse 组织列表响应结构 +type OrgListResponse struct { + Items []model.Org `json:"items"` + Total int64 `json:"total"` + Page int `json:"page"` + Size int `json:"size"` +} + +func OrgCreate(req OrgCreateRequest) (*model.Org, error) { + name := strings.TrimSpace(req.Name) if name == "" { return nil, errors.New("name required") } + o := &model.Org{ - ID: newID(), - ParentID: strings.TrimSpace(parentID), - Name: name, - Enabled: enabled, - Sort: sort, - Remark: strings.TrimSpace(remark), + ID: newID(), + ParentID: strings.TrimSpace(req.ParentID), + Name: name, + Remark: strings.TrimSpace(req.Remark), + ProtectionLevel: strings.TrimSpace(req.ProtectionLevel), + ProtectionType: strings.TrimSpace(req.ProtectionType), + AnnouncementBatch: strings.TrimSpace(req.AnnouncementBatch), + AdminRegion: strings.TrimSpace(req.AdminRegion), + Introduction: strings.TrimSpace(req.Introduction), } if err := mysql.OrgCreate(o); err != nil { logrus.WithFields(logrus.Fields{ - "func": "OrgCreateOrg", + "func": "OrgCreate", }).Warnf("mysql.OrgCreate: %v", err) return nil, err } return o, nil } -func OrgUpdateOrg(idv string, parentID, name *string, enabled *bool, sort *int, remark *string) (*model.Org, error) { +func OrgUpdate(idv string, req OrgUpdateRequest) (*model.Org, error) { oid := strings.TrimSpace(idv) if oid == "" { return nil, ErrNotFound @@ -41,45 +90,54 @@ func OrgUpdateOrg(idv string, parentID, name *string, enabled *bool, sort *int, existing, found, err := mysql.OrgByID(&oid) if err != nil { logrus.WithFields(logrus.Fields{ - "func": "OrgUpdateOrg", + "func": "OrgUpdate", }).Warnf("mysql.OrgByID: %v", err) return nil, err } if !found || existing == nil { logrus.WithFields(logrus.Fields{ - "func": "OrgUpdateOrg", + "func": "OrgUpdate", }).Warnf("mysql.OrgByID: not found") return nil, ErrNotFound } - if parentID != nil { - existing.ParentID = strings.TrimSpace(*parentID) + if req.ParentID != nil { + existing.ParentID = strings.TrimSpace(*req.ParentID) } - if name != nil { - n := strings.TrimSpace(*name) + if req.Name != nil { + n := strings.TrimSpace(*req.Name) if n == "" { return nil, errors.New("name required") } existing.Name = n } - if enabled != nil { - existing.Enabled = *enabled + if req.Remark != nil { + existing.Remark = strings.TrimSpace(*req.Remark) } - if sort != nil { - existing.Sort = *sort + if req.ProtectionLevel != nil { + existing.ProtectionLevel = strings.TrimSpace(*req.ProtectionLevel) } - if remark != nil { - existing.Remark = strings.TrimSpace(*remark) + if req.ProtectionType != nil { + existing.ProtectionType = strings.TrimSpace(*req.ProtectionType) + } + if req.AnnouncementBatch != nil { + existing.AnnouncementBatch = strings.TrimSpace(*req.AnnouncementBatch) + } + if req.AdminRegion != nil { + existing.AdminRegion = strings.TrimSpace(*req.AdminRegion) + } + if req.Introduction != nil { + existing.Introduction = strings.TrimSpace(*req.Introduction) } if err := mysql.OrgUpdate(existing); err != nil { logrus.WithFields(logrus.Fields{ - "func": "OrgUpdateOrg", + "func": "OrgUpdate", }).Warnf("mysql.OrgUpdate: %v", err) return nil, err } return existing, nil } -func OrgDeleteOrg(idv string) error { +func OrgDelete(idv string) error { oid := strings.TrimSpace(idv) if oid == "" { return ErrNotFound @@ -87,20 +145,20 @@ func OrgDeleteOrg(idv string) error { ok, err := mysql.OrgDelete(&oid) if err != nil { logrus.WithFields(logrus.Fields{ - "func": "OrgDeleteOrg", + "func": "OrgDelete", }).Warnf("mysql.OrgDelete: %v", err) return err } if !ok { logrus.WithFields(logrus.Fields{ - "func": "OrgDeleteOrg", + "func": "OrgDelete", }).Warnf("mysql.OrgDelete: not found") return ErrNotFound } return nil } -func OrgGetOrg(idv string) (*model.Org, error) { +func OrgDetail(idv string) (*model.Org, error) { oid := strings.TrimSpace(idv) if oid == "" { return nil, ErrNotFound @@ -108,20 +166,20 @@ func OrgGetOrg(idv string) (*model.Org, error) { o, found, err := mysql.OrgByID(&oid) if err != nil { logrus.WithFields(logrus.Fields{ - "func": "OrgGetOrg", + "func": "OrgDetail", }).Warnf("mysql.OrgByID: %v", err) return nil, err } if !found || o == nil { logrus.WithFields(logrus.Fields{ - "func": "OrgGetOrg", + "func": "OrgDetail", }).Warnf("mysql.OrgByID: not found") return nil, ErrNotFound } return o, nil } -func OrgListOrgs(parentID *string, page, size int) ([]model.Org, int64, error) { +func OrgPage(parentID *string, page, size int) ([]model.Org, int64, error) { if page < 1 { page = 1 }