refactor: 对齐后端样例工程规范

This commit is contained in:
2026-07-26 18:24:13 +08:00
parent 4382641e19
commit 4f2bb7e88b
66 changed files with 1869 additions and 660 deletions

View 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
}

View 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" }

View 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" }

View 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
}

View 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" }

View 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
}

View 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" }