refactor: 对齐后端样例工程规范
This commit is contained in:
29
backend/api/internal/config/config.go
Normal file
29
backend/api/internal/config/config.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// Package config 沿用 sample/server 的 BSM 配置加载与校验方式。
|
||||
package config
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"git.apinb.com/bsm-sdk/core/conf"
|
||||
)
|
||||
|
||||
// Spec 是 Platform API 的运行配置。
|
||||
var Spec SrvConfig
|
||||
|
||||
// SrvConfig 与 sample/server 配置结构保持一致。
|
||||
type SrvConfig struct {
|
||||
conf.Base `yaml:",inline"`
|
||||
Databases *conf.DBConf `yaml:"Databases"`
|
||||
Rpc map[string]conf.RpcConf `yaml:"Rpc"`
|
||||
Apm *conf.ApmConf `yaml:"APM"`
|
||||
}
|
||||
|
||||
// New 初始化 BSM 配置并校验服务监听地址。
|
||||
func New(srvKey string) {
|
||||
conf.New(srvKey, &Spec)
|
||||
Spec.Port = conf.CheckPort(Spec.Port)
|
||||
Spec.BindIP = conf.CheckIP(Spec.BindIP)
|
||||
Spec.Addr = net.JoinHostPort(Spec.BindIP, Spec.Port)
|
||||
conf.NotNil(Spec.Service, Spec.Cache)
|
||||
conf.PrintInfo(Spec.Addr)
|
||||
}
|
||||
25
backend/api/internal/impl/new.go
Normal file
25
backend/api/internal/impl/new.go
Normal file
@@ -0,0 +1,25 @@
|
||||
// Package impl 统一创建数据库、Redis、内存缓存与日志基础设施。
|
||||
package impl
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/cache/redis"
|
||||
"git.apinb.com/bsm-sdk/core/logger"
|
||||
"git.apinb.com/bsm-sdk/core/with"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/config"
|
||||
"github.com/patrickmn/go-cache"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
RedisService *redis.RedisClient
|
||||
DBService *gorm.DB
|
||||
MemoryService *cache.Cache
|
||||
)
|
||||
|
||||
// NewImpl 与 sample/server 保持一致,所有进程通过此处创建共享基础设施。
|
||||
func NewImpl() {
|
||||
MemoryService = with.Memory(nil)
|
||||
RedisService = with.RedisCache(config.Spec.Cache)
|
||||
DBService = with.Databases(config.Spec.Databases, nil)
|
||||
logger.New(nil)
|
||||
}
|
||||
18
backend/api/internal/logic/dashboard/dashboard.go
Normal file
18
backend/api/internal/logic/dashboard/dashboard.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// Package dashboard 提供平台总后台聚合指标。
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Overview 返回组织与安全运营的首期概览数据。
|
||||
func Overview(ctx *gin.Context) {
|
||||
overview, err := models.GetDashboardOverview()
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, overview)
|
||||
}
|
||||
54
backend/api/internal/logic/idn_account/idn_account.go
Normal file
54
backend/api/internal/logic/idn_account/idn_account.go
Normal file
@@ -0,0 +1,54 @@
|
||||
// Package idn_account 提供用户账户最小必要查询逻辑。
|
||||
package idn_account
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// AccountView 是 idn_account 的最小必要输出,手机号始终脱敏。
|
||||
type AccountView struct {
|
||||
Identity string `json:"identity"` // 用户主键
|
||||
PhoneMasked string `json:"phone_masked"` // 脱敏手机号
|
||||
AccountType string `json:"account_type"` // 账户类型
|
||||
Status string `json:"status"` // 账户状态
|
||||
ServiceArea string `json:"service_area"` // 服务区域
|
||||
}
|
||||
|
||||
// ListReply 是 idn_account 的标准分页响应。
|
||||
type ListReply struct {
|
||||
Total int64 `json:"total"`
|
||||
List []AccountView `json:"list"`
|
||||
}
|
||||
|
||||
// List 查询普通用户账户列表。
|
||||
func List(ctx *gin.Context) {
|
||||
page := utils.String2Int(ctx.DefaultQuery("page", "1"))
|
||||
size := utils.String2Int(ctx.DefaultQuery("size", "20"))
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if size < 1 || size > 100 {
|
||||
size = 20
|
||||
}
|
||||
list, total, err := models.ListIdnAccount(page, size)
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
views := make([]AccountView, 0, len(list))
|
||||
for _, item := range list {
|
||||
views = append(views, AccountView{Identity: item.Identity.String(), PhoneMasked: maskPhone(item.Phone), AccountType: item.AccountType, Status: item.Status, ServiceArea: item.ServiceArea})
|
||||
}
|
||||
infra.Response.Success(ctx, ListReply{Total: total, List: views})
|
||||
}
|
||||
|
||||
// maskPhone 遵循敏感数据最小展示原则。
|
||||
func maskPhone(phone string) string {
|
||||
if len(phone) < 7 {
|
||||
return "***"
|
||||
}
|
||||
return phone[:3] + "****" + phone[len(phone)-4:]
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Package org_delivery_point 提供配送点管理查询逻辑。
|
||||
package org_delivery_point
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ListReply 是 org_delivery_point 的标准分页响应。
|
||||
type ListReply struct {
|
||||
Total int64 `json:"total"`
|
||||
List []models.OrgDeliveryPoint `json:"list"`
|
||||
}
|
||||
|
||||
// List 查询配送点分页列表。
|
||||
func List(ctx *gin.Context) {
|
||||
page, size := pageSize(ctx)
|
||||
list, total, err := models.ListOrgDeliveryPoint(page, size)
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, ListReply{Total: total, List: list})
|
||||
}
|
||||
|
||||
func pageSize(ctx *gin.Context) (int, int) {
|
||||
page := utils.String2Int(ctx.DefaultQuery("page", "1"))
|
||||
size := utils.String2Int(ctx.DefaultQuery("size", "20"))
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if size < 1 || size > 100 {
|
||||
size = 20
|
||||
}
|
||||
return page, size
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Package org_gas_station 提供气站管理的 HTTP 业务逻辑。
|
||||
package org_gas_station
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// CreateRequest 是创建 org_gas_station 的请求体。
|
||||
type CreateRequest struct {
|
||||
StationCode string `json:"station_code" binding:"required,max=32"`
|
||||
Name string `json:"name" binding:"required,max=128"`
|
||||
Principal string `json:"principal" binding:"required,max=64"`
|
||||
ServiceArea string `json:"service_area" binding:"required,max=128"`
|
||||
}
|
||||
|
||||
// ListReply 是标准分页响应。
|
||||
type ListReply struct {
|
||||
Total int64 `json:"total"`
|
||||
List []models.OrgGasStation `json:"list"`
|
||||
}
|
||||
|
||||
// Create 创建待审核气站并由数据库层保证唯一编码。
|
||||
func Create(ctx *gin.Context) {
|
||||
var request CreateRequest
|
||||
if err := ctx.ShouldBindJSON(&request); err != nil {
|
||||
infra.Response.Error(ctx, errcode.ErrInvalidArgument)
|
||||
return
|
||||
}
|
||||
data := models.OrgGasStation{StationCode: request.StationCode, Name: request.Name, Principal: request.Principal, ServiceArea: request.ServiceArea}
|
||||
data.Identity = models.NewIdentity()
|
||||
data.Status = "draft"
|
||||
data.Version = 1
|
||||
if err := models.CreateOrgGasStation(&data); err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, data)
|
||||
}
|
||||
|
||||
// List 查询气站分页列表。
|
||||
func List(ctx *gin.Context) {
|
||||
page := utils.String2Int(ctx.DefaultQuery("page", "1"))
|
||||
size := utils.String2Int(ctx.DefaultQuery("size", "20"))
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if size < 1 || size > 100 {
|
||||
size = 20
|
||||
}
|
||||
list, total, err := models.ListOrgGasStation(page, size)
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, ListReply{Total: total, List: list})
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Package org_service_person 提供服务人员管理查询逻辑。
|
||||
package org_service_person
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ListReply 是 org_service_person 的标准分页响应。
|
||||
type ListReply struct {
|
||||
Total int64 `json:"total"`
|
||||
List []models.OrgServicePerson `json:"list"`
|
||||
}
|
||||
|
||||
// List 查询服务人员分页列表。
|
||||
func List(ctx *gin.Context) {
|
||||
page := utils.String2Int(ctx.DefaultQuery("page", "1"))
|
||||
size := utils.String2Int(ctx.DefaultQuery("size", "20"))
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if size < 1 || size > 100 {
|
||||
size = 20
|
||||
}
|
||||
list, total, err := models.ListOrgServicePerson(page, size)
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, ListReply{Total: total, List: list})
|
||||
}
|
||||
12
backend/api/internal/logic/ping/hello.go
Normal file
12
backend/api/internal/logic/ping/hello.go
Normal file
@@ -0,0 +1,12 @@
|
||||
// Package ping 提供匿名健康检查接口。
|
||||
package ping
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Hello 返回 API 进程健康状态。
|
||||
func Hello(ctx *gin.Context) {
|
||||
infra.Response.Success(ctx, gin.H{"service": "platform-api", "status": "ok"})
|
||||
}
|
||||
33
backend/api/internal/logic/saf_event/saf_event.go
Normal file
33
backend/api/internal/logic/saf_event/saf_event.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// Package saf_event 提供安全事件查询逻辑。
|
||||
package saf_event
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/infra"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ListReply 是 saf_event 的标准分页响应。
|
||||
type ListReply struct {
|
||||
Total int64 `json:"total"`
|
||||
List []models.SafEvent `json:"list"`
|
||||
}
|
||||
|
||||
// List 查询安全事件列表。
|
||||
func List(ctx *gin.Context) {
|
||||
page := utils.String2Int(ctx.DefaultQuery("page", "1"))
|
||||
size := utils.String2Int(ctx.DefaultQuery("size", "20"))
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if size < 1 || size > 100 {
|
||||
size = 20
|
||||
}
|
||||
list, total, err := models.ListSafEvent(page, size)
|
||||
if err != nil {
|
||||
infra.Response.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
infra.Response.Success(ctx, ListReply{Total: total, List: list})
|
||||
}
|
||||
28
backend/api/internal/models/entity.go
Normal file
28
backend/api/internal/models/entity.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// Package models 定义与数据库表同名的领域模型和数据访问方法。
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Entity 是所有主表共享字段;identity 必须由应用生成 UUID V7,禁止自增主键。
|
||||
type Entity struct {
|
||||
Identity uuid.UUID `gorm:"column:identity;type:uuid;primaryKey" json:"identity"` // 主键,UUID V7
|
||||
CreatedAt time.Time `gorm:"column:created_at;type:timestamptz;not null" json:"created_at"` // 创建时间
|
||||
UpdatedAt time.Time `gorm:"column:updated_at;type:timestamptz;not null" json:"updated_at"` // 更新时间
|
||||
CreatedByIdentity *uuid.UUID `gorm:"column:created_by_identity;type:uuid" json:"created_by_identity,omitempty"` // 创建人主键
|
||||
UpdatedByIdentity *uuid.UUID `gorm:"column:updated_by_identity;type:uuid" json:"updated_by_identity,omitempty"` // 更新人主键
|
||||
Status string `gorm:"column:status;type:varchar(32);not null;default:'draft'" json:"status"` // 业务状态
|
||||
Version int `gorm:"column:version;not null;default:1" json:"version"` // 乐观锁版本
|
||||
}
|
||||
|
||||
// NewIdentity 生成时间有序 UUID V7,生成失败属于不可恢复的运行时错误。
|
||||
func NewIdentity() uuid.UUID {
|
||||
identity, err := uuid.NewV7()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return identity
|
||||
}
|
||||
16
backend/api/internal/models/idn_account.go
Normal file
16
backend/api/internal/models/idn_account.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package models
|
||||
|
||||
import "git.apinb.com/bsm-sdk/core/database"
|
||||
|
||||
// IdnAccount 对应 idn_account,表示用户或服务人员身份账户。
|
||||
type IdnAccount struct {
|
||||
Entity
|
||||
Phone string `gorm:"column:phone;type:varchar(32);uniqueIndex;not null" json:"phone"` // 手机号,响应时需脱敏
|
||||
AccountType string `gorm:"column:account_type;type:varchar(32);not null" json:"account_type"` // 账户类型
|
||||
ServiceArea string `gorm:"column:service_area;type:varchar(128);not null" json:"service_area"` // 服务区域
|
||||
}
|
||||
|
||||
func init() { database.AppendMigrate(&IdnAccount{}) }
|
||||
|
||||
// TableName 返回与模型、文件名一致的单数数据表名。
|
||||
func (table *IdnAccount) TableName() string { return "idn_account" }
|
||||
17
backend/api/internal/models/org_delivery_point.go
Normal file
17
backend/api/internal/models/org_delivery_point.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package models
|
||||
|
||||
import "git.apinb.com/bsm-sdk/core/database"
|
||||
|
||||
// OrgDeliveryPoint 对应 org_delivery_point,表示末端配送组织单元。
|
||||
type OrgDeliveryPoint struct {
|
||||
Entity
|
||||
DeliveryCode string `gorm:"column:delivery_code;type:varchar(32);uniqueIndex;not null" json:"delivery_code"` // 配送点编码
|
||||
GasStationIdentity string `gorm:"column:gas_station_identity;type:uuid" json:"gas_station_identity"` // 归属气站主键
|
||||
Name string `gorm:"column:name;type:varchar(128);not null" json:"name"` // 配送点名称
|
||||
ServiceArea string `gorm:"column:service_area;type:varchar(128);not null" json:"service_area"` // 服务区域
|
||||
}
|
||||
|
||||
func init() { database.AppendMigrate(&OrgDeliveryPoint{}) }
|
||||
|
||||
// TableName 返回与模型、文件名一致的单数数据表名。
|
||||
func (table *OrgDeliveryPoint) TableName() string { return "org_delivery_point" }
|
||||
60
backend/api/internal/models/org_gas_station.go
Normal file
60
backend/api/internal/models/org_gas_station.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"git.apinb.com/bsm-sdk/core/database"
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/impl"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// OrgGasStation 对应 org_gas_station,表示可燃气体站经营主体。
|
||||
type OrgGasStation struct {
|
||||
Entity
|
||||
StationCode string `gorm:"column:station_code;type:varchar(32);uniqueIndex;not null" json:"station_code"` // 气站编码
|
||||
Name string `gorm:"column:name;type:varchar(128);not null" json:"name"` // 气站名称
|
||||
Principal string `gorm:"column:principal;type:varchar(64);not null" json:"principal"` // 负责人
|
||||
ServiceArea string `gorm:"column:service_area;type:varchar(128);not null" json:"service_area"` // 服务区域
|
||||
}
|
||||
|
||||
func init() {
|
||||
database.AppendMigrate(&OrgGasStation{})
|
||||
}
|
||||
|
||||
// TableName 返回与模型、文件名一致的单数数据表名。
|
||||
func (table *OrgGasStation) TableName() string { return "org_gas_station" }
|
||||
|
||||
// CreateOrgGasStation 创建待审核气站。
|
||||
func CreateOrgGasStation(data *OrgGasStation) error {
|
||||
if err := impl.DBService.Create(data).Error; err != nil {
|
||||
return errcode.ErrDB
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListOrgGasStation 按创建时间倒序查询气站。
|
||||
func ListOrgGasStation(page, size int) ([]OrgGasStation, int64, error) {
|
||||
var list []OrgGasStation
|
||||
var total int64
|
||||
databaseQuery := impl.DBService.Model(&OrgGasStation{})
|
||||
if err := databaseQuery.Count(&total).Error; err != nil {
|
||||
return nil, 0, errcode.ErrDB
|
||||
}
|
||||
if err := databaseQuery.Order("created_at desc").Offset((page - 1) * size).Limit(size).Find(&list).Error; err != nil {
|
||||
return nil, 0, errcode.ErrDB
|
||||
}
|
||||
return list, total, nil
|
||||
}
|
||||
|
||||
// GetOrgGasStationByIdentity 查询单个气站。
|
||||
func GetOrgGasStationByIdentity(identity string) (*OrgGasStation, error) {
|
||||
var data OrgGasStation
|
||||
if err := impl.DBService.Where("identity = ?", identity).First(&data).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, errcode.ErrRecordNotFound
|
||||
}
|
||||
return nil, errcode.ErrDB
|
||||
}
|
||||
return &data, nil
|
||||
}
|
||||
20
backend/api/internal/models/org_service_person.go
Normal file
20
backend/api/internal/models/org_service_person.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package models
|
||||
|
||||
import "git.apinb.com/bsm-sdk/core/database"
|
||||
|
||||
// OrgServicePerson 对应 org_service_person,表示安装维修、安检或配送服务人员。
|
||||
type OrgServicePerson struct {
|
||||
Entity
|
||||
AccountIdentity string `gorm:"column:account_identity;type:uuid;uniqueIndex" json:"account_identity"` // 关联 idn_account 主键
|
||||
GasStationIdentity string `gorm:"column:gas_station_identity;type:uuid" json:"gas_station_identity"` // 归属气站主键
|
||||
DeliveryPointIdentity string `gorm:"column:delivery_point_identity;type:uuid" json:"delivery_point_identity"` // 主归属配送点主键
|
||||
Name string `gorm:"column:name;type:varchar(64);not null" json:"name"` // 服务人员姓名
|
||||
Roles string `gorm:"column:roles;type:varchar(128);not null" json:"roles"` // 可执行角色集合
|
||||
WorkStatus string `gorm:"column:work_status;type:varchar(32);not null" json:"work_status"` // 上班与接单状态
|
||||
CredentialStatus string `gorm:"column:credential_status;type:varchar(32);not null" json:"credential_status"` // 资质状态
|
||||
}
|
||||
|
||||
func init() { database.AppendMigrate(&OrgServicePerson{}) }
|
||||
|
||||
// TableName 返回与模型、文件名一致的单数数据表名。
|
||||
func (table *OrgServicePerson) TableName() string { return "org_service_person" }
|
||||
89
backend/api/internal/models/query.go
Normal file
89
backend/api/internal/models/query.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package models
|
||||
|
||||
import "git.apinb.com/heqiapp/platforms/backend/api/internal/impl"
|
||||
|
||||
// DashboardOverview 是平台总后台的安全与组织聚合指标。
|
||||
type DashboardOverview struct {
|
||||
GasStationCount int64 `json:"gas_station_count"` // 启用气站数量
|
||||
DeliveryPointCount int64 `json:"delivery_point_count"` // 启用配送点数量
|
||||
ServicePersonCount int64 `json:"service_person_count"` // 在岗服务人员数量
|
||||
UserCount int64 `json:"user_count"` // 启用普通用户数量
|
||||
PendingSafetyCount int64 `json:"pending_safety_count"` // 待处理安全事件数量
|
||||
}
|
||||
|
||||
// GetDashboardOverview 通过独立查询返回首期仪表盘指标。
|
||||
func GetDashboardOverview() (DashboardOverview, error) {
|
||||
var overview DashboardOverview
|
||||
if err := impl.DBService.Model(&OrgGasStation{}).Where("status = ?", "enabled").Count(&overview.GasStationCount).Error; err != nil {
|
||||
return DashboardOverview{}, err
|
||||
}
|
||||
if err := impl.DBService.Model(&OrgDeliveryPoint{}).Where("status = ?", "enabled").Count(&overview.DeliveryPointCount).Error; err != nil {
|
||||
return DashboardOverview{}, err
|
||||
}
|
||||
if err := impl.DBService.Model(&OrgServicePerson{}).Where("work_status = ?", "on_duty").Count(&overview.ServicePersonCount).Error; err != nil {
|
||||
return DashboardOverview{}, err
|
||||
}
|
||||
if err := impl.DBService.Model(&IdnAccount{}).Where("account_type = ? AND status = ?", "user", "enabled").Count(&overview.UserCount).Error; err != nil {
|
||||
return DashboardOverview{}, err
|
||||
}
|
||||
if err := impl.DBService.Model(&SafEvent{}).Where("status = ?", "pending").Count(&overview.PendingSafetyCount).Error; err != nil {
|
||||
return DashboardOverview{}, err
|
||||
}
|
||||
return overview, nil
|
||||
}
|
||||
|
||||
// ListOrgDeliveryPoint 返回配送点分页列表。
|
||||
func ListOrgDeliveryPoint(page, size int) ([]OrgDeliveryPoint, int64, error) {
|
||||
var list []OrgDeliveryPoint
|
||||
var total int64
|
||||
databaseQuery := impl.DBService.Model(&OrgDeliveryPoint{})
|
||||
if err := databaseQuery.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if err := databaseQuery.Order("created_at desc").Offset((page - 1) * size).Limit(size).Find(&list).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return list, total, nil
|
||||
}
|
||||
|
||||
// ListOrgServicePerson 返回服务人员分页列表。
|
||||
func ListOrgServicePerson(page, size int) ([]OrgServicePerson, int64, error) {
|
||||
var list []OrgServicePerson
|
||||
var total int64
|
||||
databaseQuery := impl.DBService.Model(&OrgServicePerson{})
|
||||
if err := databaseQuery.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if err := databaseQuery.Order("created_at desc").Offset((page - 1) * size).Limit(size).Find(&list).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return list, total, nil
|
||||
}
|
||||
|
||||
// ListIdnAccount 返回普通用户分页列表,手机号脱敏由前端展示层处理。
|
||||
func ListIdnAccount(page, size int) ([]IdnAccount, int64, error) {
|
||||
var list []IdnAccount
|
||||
var total int64
|
||||
databaseQuery := impl.DBService.Model(&IdnAccount{}).Where("account_type = ?", "user")
|
||||
if err := databaseQuery.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if err := databaseQuery.Order("created_at desc").Offset((page - 1) * size).Limit(size).Find(&list).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return list, total, nil
|
||||
}
|
||||
|
||||
// ListSafEvent 返回安全事件分页列表。
|
||||
func ListSafEvent(page, size int) ([]SafEvent, int64, error) {
|
||||
var list []SafEvent
|
||||
var total int64
|
||||
databaseQuery := impl.DBService.Model(&SafEvent{})
|
||||
if err := databaseQuery.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if err := databaseQuery.Order("level asc, created_at desc").Offset((page - 1) * size).Limit(size).Find(&list).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return list, total, nil
|
||||
}
|
||||
18
backend/api/internal/models/saf_event.go
Normal file
18
backend/api/internal/models/saf_event.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package models
|
||||
|
||||
import "git.apinb.com/bsm-sdk/core/database"
|
||||
|
||||
// SafEvent 对应 saf_event,表示需要平台跟踪处置的安全事件。
|
||||
type SafEvent struct {
|
||||
Entity
|
||||
EventCode string `gorm:"column:event_code;type:varchar(32);uniqueIndex;not null" json:"event_code"` // 安全事件编码
|
||||
Level int `gorm:"column:level;type:integer;not null" json:"level"` // 风险等级,1 至 3 级
|
||||
Title string `gorm:"column:title;type:varchar(256);not null" json:"title"` // 事件说明
|
||||
}
|
||||
|
||||
func init() {
|
||||
database.AppendMigrate(&SafEvent{})
|
||||
}
|
||||
|
||||
// TableName 返回与模型、文件名一致的单数数据表名。
|
||||
func (table *SafEvent) TableName() string { return "saf_event" }
|
||||
36
backend/api/internal/routers/register.go
Normal file
36
backend/api/internal/routers/register.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// Package routers 注册与 sample/server 一致的匿名和 JWT 受保护路由组。
|
||||
package routers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.apinb.com/bsm-sdk/core/middleware"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/logic/dashboard"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/logic/idn_account"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/logic/org_delivery_point"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/logic/org_gas_station"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/logic/org_service_person"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/logic/ping"
|
||||
"git.apinb.com/heqiapp/platforms/backend/api/internal/logic/saf_event"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Register 注册路由,请求地址格式: /{serviceKey}/v1/{domain}/{resource}。
|
||||
func Register(srvKey string, engine *gin.Engine) {
|
||||
v1Key := fmt.Sprintf("/%s/%s", srvKey, "v1")
|
||||
anonymous := engine.Group(v1Key)
|
||||
anonymous.GET("/ping/hello", ping.Hello)
|
||||
|
||||
protected := engine.Group(v1Key)
|
||||
protected.Use(middleware.JwtAuth(true))
|
||||
{
|
||||
protected.GET("/dashboard/overview", dashboard.Overview)
|
||||
gasStationGroup := protected.Group("/organization/org_gas_station")
|
||||
gasStationGroup.POST("", org_gas_station.Create)
|
||||
gasStationGroup.GET("", org_gas_station.List)
|
||||
protected.GET("/organization/org_delivery_point", org_delivery_point.List)
|
||||
protected.GET("/organization/org_service_person", org_service_person.List)
|
||||
protected.GET("/identity/idn_account", idn_account.List)
|
||||
protected.GET("/safety/saf_event", saf_event.List)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user