chore: 初始化仓库基线(AGENTS.md、git 规范、敏感文件排除)
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// User 用户表
|
||||
type User struct {
|
||||
ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()" json:"id"`
|
||||
Username string `gorm:"unique" json:"username"`
|
||||
Email string `gorm:"unique" json:"email"`
|
||||
PasswordHash string `gorm:"column:password_hash" json:"passwordHash"`
|
||||
FullName *string `gorm:"column:full_name" json:"fullName,omitempty"`
|
||||
Role string `gorm:"default:user" json:"role"`
|
||||
Active bool `gorm:"default:true" json:"active"`
|
||||
CreatedAt time.Time `gorm:"type:timestamptz" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"type:timestamptz" json:"updatedAt"`
|
||||
}
|
||||
|
||||
func (User) TableName() string { return "users" }
|
||||
|
||||
// Room 房间表
|
||||
type Room struct {
|
||||
ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()" json:"id"`
|
||||
Name string `json:"name"`
|
||||
Code *string `json:"code,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
Capacity *int `gorm:"type:int" json:"capacity,omitempty"`
|
||||
Stage *string `gorm:"size:32" json:"stage,omitempty"`
|
||||
Status string `gorm:"default:active" json:"status"`
|
||||
CreatedAt time.Time `gorm:"type:timestamptz" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"type:timestamptz" json:"updatedAt"`
|
||||
}
|
||||
|
||||
func (Room) TableName() string { return "rooms" }
|
||||
|
||||
// Device 设备表
|
||||
type Device struct {
|
||||
ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()" json:"id"`
|
||||
DeviceKey string `gorm:"column:device_key;unique" json:"deviceKey"`
|
||||
Name string `json:"name"`
|
||||
Kind string `gorm:"default:sensor" json:"kind"`
|
||||
Model *string `json:"model,omitempty"`
|
||||
Firmware *string `json:"firmware,omitempty"`
|
||||
OnlineStatus string `gorm:"column:online_status;default:online" json:"onlineStatus"`
|
||||
LastSeen *time.Time `gorm:"column:last_seen;type:timestamptz" json:"lastSeen,omitempty"`
|
||||
RoomID string `gorm:"column:room_id;type:uuid;index" json:"roomId"`
|
||||
Topic *string `gorm:"column:topic" json:"topic,omitempty"` // 设备上行主题(持久化,防止后端重启丢失)
|
||||
CreatedAt time.Time `gorm:"type:timestamptz" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"type:timestamptz" json:"updatedAt"`
|
||||
}
|
||||
|
||||
func (Device) TableName() string { return "devices" }
|
||||
|
||||
// Sensor 传感器表
|
||||
type Sensor struct {
|
||||
ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()" json:"id"`
|
||||
Name string `json:"name"`
|
||||
Metric string `json:"metric"`
|
||||
Unit *string `json:"unit,omitempty"`
|
||||
DataType *string `gorm:"column:data_type" json:"dataType,omitempty"`
|
||||
DeviceID string `gorm:"column:device_id;type:uuid;index" json:"deviceId"`
|
||||
CreatedAt time.Time `gorm:"type:timestamptz" json:"createdAt"`
|
||||
}
|
||||
|
||||
func (Sensor) TableName() string { return "sensors" }
|
||||
|
||||
// Threshold 阈值表
|
||||
type Threshold struct {
|
||||
ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()" json:"id"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
MinValue float64 `gorm:"column:min_value;type:float" json:"minValue"`
|
||||
MaxValue float64 `gorm:"column:max_value;type:float" json:"maxValue"`
|
||||
DebounceSeconds int `gorm:"column:debounce_seconds;type:int;default:5" json:"debounceSeconds"`
|
||||
Severity int `gorm:"type:int;default:3" json:"severity"`
|
||||
Enabled bool `gorm:"default:true" json:"enabled"`
|
||||
SensorID string `gorm:"column:sensor_id;type:uuid;index" json:"sensorId"`
|
||||
CreatedAt time.Time `gorm:"type:timestamptz" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"type:timestamptz" json:"updatedAt"`
|
||||
}
|
||||
|
||||
func (Threshold) TableName() string { return "thresholds" }
|
||||
|
||||
// Alarm 告警表
|
||||
type Alarm struct {
|
||||
ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()" json:"id"`
|
||||
Code *string `json:"code,omitempty"`
|
||||
Title *string `json:"title,omitempty"`
|
||||
Message *string `json:"message,omitempty"`
|
||||
Severity *string `json:"severity,omitempty"`
|
||||
Open bool `gorm:"default:true;index:idx_alarms_device_open_triggered,priority:2" json:"open"`
|
||||
Acknowledged bool `gorm:"default:false" json:"acknowledged"`
|
||||
AcknowledgedAt *time.Time `gorm:"column:acknowledged_at;type:timestamptz" json:"acknowledgedAt,omitempty"`
|
||||
TriggeredAt time.Time `gorm:"column:triggered_at;type:timestamptz;index:idx_alarms_device_open_triggered,priority:3" json:"triggeredAt"`
|
||||
ResolvedAt *time.Time `gorm:"column:resolved_at;type:timestamptz" json:"resolvedAt,omitempty"`
|
||||
DeviceKey *string `gorm:"column:device_key;index:idx_alarms_device_open_triggered,priority:1" json:"deviceKey,omitempty"`
|
||||
Metric *string `json:"metric,omitempty"`
|
||||
Value *float64 `gorm:"type:float" json:"value,omitempty"`
|
||||
ThresholdMin *float64 `gorm:"column:threshold_min;type:float" json:"thresholdMin,omitempty"`
|
||||
ThresholdMax *float64 `gorm:"column:threshold_max;type:float" json:"thresholdMax,omitempty"`
|
||||
}
|
||||
|
||||
func (Alarm) TableName() string { return "alarms" }
|
||||
|
||||
// Camera 摄像头表
|
||||
type Camera struct {
|
||||
ID uint `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||
RoomID *string `gorm:"column:room_id;index" json:"roomId,omitempty"`
|
||||
Code string `gorm:"size:64" json:"code"`
|
||||
Name string `gorm:"size:128" json:"name"`
|
||||
RtspURL *string `gorm:"column:rtsp_url;size:512" json:"rtspUrl,omitempty"`
|
||||
HTTPURL *string `gorm:"column:http_url;size:512" json:"httpUrl,omitempty"`
|
||||
Username *string `gorm:"size:64" json:"username,omitempty"`
|
||||
PasswordEnc *string `gorm:"column:password_enc;size:255" json:"passwordEnc,omitempty"`
|
||||
Position *string `gorm:"size:255" json:"position,omitempty"`
|
||||
Resolution *string `gorm:"size:32" json:"resolution,omitempty"`
|
||||
FPS *int `gorm:"type:int" json:"fps,omitempty"`
|
||||
IsOnline bool `gorm:"column:is_online;default:true" json:"isOnline"`
|
||||
GbDeviceID *string `gorm:"column:gb_device_id;size:20" json:"gbDeviceId,omitempty"`
|
||||
GbChannelID *string `gorm:"column:gb_channel_id;size:20" json:"gbChannelId,omitempty"`
|
||||
GbAuthID *string `gorm:"column:gb_auth_id;size:20" json:"gbAuthId,omitempty"`
|
||||
GbAuthPassword *string `gorm:"column:gb_auth_password;size:255" json:"gbAuthPassword,omitempty"`
|
||||
GbStreamType *string `gorm:"column:gb_stream_type;size:10" json:"gbStreamType,omitempty"`
|
||||
GbTransport *string `gorm:"column:gb_transport;size:10" json:"gbTransport,omitempty"`
|
||||
GbAlarmChannelID *string `gorm:"column:gb_alarm_channel_id;size:20" json:"gbAlarmChannelId,omitempty"`
|
||||
GbVoiceChannelID *string `gorm:"column:gb_voice_channel_id;size:20" json:"gbVoiceChannelId,omitempty"`
|
||||
GbManufacturer *string `gorm:"column:gb_manufacturer;size:64" json:"gbManufacturer,omitempty"`
|
||||
ManufacturerID *string `gorm:"column:manufacturer_id;size:64" json:"manufacturerId,omitempty"`
|
||||
// 以下字段不在数据库中,运行时通过 WVP API 填充
|
||||
StreamURL *string `gorm:"-" json:"streamUrl,omitempty"`
|
||||
HlsURL *string `gorm:"-" json:"hlsUrl,omitempty"`
|
||||
FlvURL *string `gorm:"-" json:"flvUrl,omitempty"`
|
||||
WebrtcURL *string `gorm:"-" json:"webrtcUrl,omitempty"`
|
||||
SnapshotURL *string `gorm:"-" json:"snapshotUrl,omitempty"`
|
||||
Online bool `gorm:"-" json:"online"`
|
||||
Enabled bool `gorm:"default:true" json:"enabled"`
|
||||
CreatedAt time.Time `gorm:"type:timestamptz" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"type:timestamptz" json:"updatedAt"`
|
||||
}
|
||||
|
||||
func (Camera) TableName() string { return "cameras" }
|
||||
|
||||
// AfterFind 查询后同步 IsOnline → Online
|
||||
func (c *Camera) AfterFind(tx *gorm.DB) error {
|
||||
c.Online = c.IsOnline
|
||||
return nil
|
||||
}
|
||||
|
||||
// VideoClip 视频片段表
|
||||
type VideoClip struct {
|
||||
ID uint `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||
Trigger string `gorm:"default:alarm" json:"trigger"`
|
||||
FilePath *string `gorm:"column:file_path" json:"filePath,omitempty"`
|
||||
DurationSec float64 `gorm:"column:duration_sec;type:real;default:0" json:"durationSec"`
|
||||
StartAt time.Time `gorm:"column:start_at;type:timestamptz" json:"startAt"`
|
||||
EndAt *time.Time `gorm:"column:end_at;type:timestamptz" json:"endAt,omitempty"`
|
||||
Resolution *string `json:"resolution,omitempty"`
|
||||
SizeBytes *int64 `gorm:"column:size_bytes;type:bigint" json:"sizeBytes,omitempty"`
|
||||
Notes *string `json:"notes,omitempty"`
|
||||
CameraID string `gorm:"column:camera_id;index" json:"cameraId"`
|
||||
RoomID *string `gorm:"column:room_id;index" json:"roomId,omitempty"`
|
||||
AlarmID *string `gorm:"column:alarm_id;index" json:"alarmId,omitempty"`
|
||||
CreatedAt time.Time `gorm:"type:timestamptz" json:"createdAt"`
|
||||
UpdatedAt time.Time `gorm:"type:timestamptz" json:"updatedAt"`
|
||||
S3Bucket *string `gorm:"column:s3_bucket" json:"s3Bucket,omitempty"`
|
||||
S3Key *string `gorm:"column:s3_key" json:"s3Key,omitempty"`
|
||||
// 以下字段不在数据库中,运行时填充
|
||||
PlaybackURL *string `gorm:"-" json:"playbackUrl,omitempty"`
|
||||
Format string `gorm:"-" json:"format"`
|
||||
}
|
||||
|
||||
func (VideoClip) TableName() string { return "video_clips" }
|
||||
|
||||
// AuditLog 审计日志表
|
||||
type AuditLog struct {
|
||||
ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()" json:"id"`
|
||||
UserID *string `gorm:"column:user_id;type:uuid;index:idx_audit_logs_user_created,priority:1" json:"userId,omitempty"`
|
||||
Username *string `json:"username,omitempty"`
|
||||
Action string `gorm:"index:idx_audit_logs_action_created,priority:1" json:"action"`
|
||||
Resource *string `gorm:"index:idx_audit_logs_resource_target,priority:1" json:"resource,omitempty"`
|
||||
TargetID *string `gorm:"column:target_id;index:idx_audit_logs_resource_target,priority:2" json:"targetId,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
IPAddress *string `gorm:"column:ip_address" json:"ipAddress,omitempty"`
|
||||
UserAgent *string `gorm:"column:user_agent" json:"userAgent,omitempty"`
|
||||
Metadata json.RawMessage `gorm:"column:metadata;type:jsonb" json:"metadata,omitempty"`
|
||||
CreatedAt time.Time `gorm:"type:timestamptz;index:idx_audit_logs_user_created,priority:2;index:idx_audit_logs_action_created,priority:2" json:"createdAt"`
|
||||
}
|
||||
|
||||
func (AuditLog) TableName() string { return "audit_logs" }
|
||||
|
||||
// Telemetry 遥测数据表
|
||||
type Telemetry struct {
|
||||
ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()" json:"id"`
|
||||
DeviceKey string `gorm:"column:device_key;index:idx_telemetry_device_timestamp,priority:1" json:"deviceKey"`
|
||||
Metric string `json:"metric"`
|
||||
Value float64 `gorm:"type:float" json:"value"`
|
||||
Timestamp time.Time `gorm:"type:timestamptz;index:idx_telemetry_device_timestamp,priority:2" json:"timestamp"`
|
||||
}
|
||||
|
||||
func (Telemetry) TableName() string { return "telemetry" }
|
||||
@@ -0,0 +1,43 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
// 角色常量
|
||||
const (
|
||||
RoleAdmin = "admin"
|
||||
RoleOperator = "operator"
|
||||
RoleViewer = "viewer"
|
||||
RoleFarmer = "farmer"
|
||||
)
|
||||
|
||||
// AllRoles 系统支持的全部角色
|
||||
var AllRoles = []string{RoleAdmin, RoleOperator, RoleViewer, RoleFarmer}
|
||||
|
||||
// RoleNames 角色中文名映射
|
||||
var RoleNames = map[string]string{
|
||||
RoleAdmin: "管理员",
|
||||
RoleOperator: "操作员",
|
||||
RoleViewer: "查看者",
|
||||
RoleFarmer: "养殖员",
|
||||
}
|
||||
|
||||
// Permission 权限表
|
||||
type Permission struct {
|
||||
ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()" json:"id"`
|
||||
Code string `gorm:"column:code;uniqueIndex" json:"code"` // 权限码,如 device:control
|
||||
Name string `gorm:"column:name" json:"name"` // 权限名称
|
||||
Description *string `gorm:"column:description" json:"description,omitempty"`
|
||||
CreatedAt time.Time `gorm:"type:timestamptz" json:"createdAt"`
|
||||
}
|
||||
|
||||
func (Permission) TableName() string { return "permissions" }
|
||||
|
||||
// RolePermission 角色-权限关联表
|
||||
type RolePermission struct {
|
||||
ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()" json:"id"`
|
||||
Role string `gorm:"column:role;index:idx_role_permissions_role_code,unique,priority:1" json:"role"`
|
||||
PermissionID string `gorm:"column:permission_id;type:uuid;index:idx_role_permissions_role_code,unique,priority:2" json:"permissionId"`
|
||||
CreatedAt time.Time `gorm:"type:timestamptz" json:"createdAt"`
|
||||
}
|
||||
|
||||
func (RolePermission) TableName() string { return "role_permissions" }
|
||||
@@ -0,0 +1,50 @@
|
||||
package model
|
||||
|
||||
// PermissionDef 权限定义(用于种子数据初始化)
|
||||
type PermissionDef struct {
|
||||
Code string
|
||||
Name string
|
||||
Description string
|
||||
}
|
||||
|
||||
// AllPermissions 系统全部权限定义
|
||||
var AllPermissions = []PermissionDef{
|
||||
{"dashboard:view", "看板查看", "查看仪表盘"},
|
||||
{"room:read", "蚕房查看", "查看蚕房列表和详情"},
|
||||
{"room:write", "蚕房管理", "新增、编辑、删除蚕房"},
|
||||
{"device:read", "设备查看", "查看设备列表和状态"},
|
||||
{"device:control", "设备控制", "下发设备控制命令"},
|
||||
{"threshold:read", "阈值查看", "查看阈值配置"},
|
||||
{"threshold:write", "阈值管理", "新增、编辑、删除阈值"},
|
||||
{"alarm:read", "告警查看", "查看告警列表"},
|
||||
{"alarm:ack", "告警确认", "确认和解除告警"},
|
||||
{"video:read", "视频查看", "查看视频监控和回放"},
|
||||
{"video:record", "视频录制", "启动和停止视频录制"},
|
||||
{"energy:view", "能耗查看", "查看能耗数据"},
|
||||
{"log:read", "日志查看", "查看控制日志"},
|
||||
{"user:manage", "用户管理", "管理用户、角色和权限"},
|
||||
{"audit:read", "审计查看", "查看审计日志"},
|
||||
}
|
||||
|
||||
// RolePermissionMap 角色-权限码映射(种子数据)
|
||||
var RolePermissionMap = map[string][]string{
|
||||
RoleAdmin: {
|
||||
"dashboard:view", "room:read", "room:write", "device:read", "device:control",
|
||||
"threshold:read", "threshold:write", "alarm:read", "alarm:ack",
|
||||
"video:read", "video:record", "energy:view", "log:read",
|
||||
"user:manage", "audit:read",
|
||||
},
|
||||
RoleOperator: {
|
||||
"dashboard:view", "room:read", "room:write", "device:read", "device:control",
|
||||
"threshold:read", "threshold:write", "alarm:read", "alarm:ack",
|
||||
"video:read", "video:record", "energy:view", "log:read",
|
||||
},
|
||||
RoleViewer: {
|
||||
"dashboard:view", "room:read", "device:read",
|
||||
"threshold:read", "alarm:read", "video:read", "energy:view",
|
||||
},
|
||||
RoleFarmer: {
|
||||
"dashboard:view", "room:read", "device:read", "device:control",
|
||||
"alarm:read", "alarm:ack", "video:read", "energy:view",
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user