Files
opsx-licence/backend/internal/model/license.go
T
Logan.Li 4ae318335c feat: 完成 opsx-licence 许可证管理平台全栈实现
基于 opsx-web-lite 框架(Go+Gin+Vue3+Element Plus)构建许可证管理服务器,
业务域参考 Licence 服务器 Web 版。

【后端 - 4层架构】
- 认证:单 Admin 表 + JWT(HS256)
- 核心授权域:Product / Customer / License / Activation
  · License 生成/验证/激活/机器绑定/心跳/续期/吊销
  · 客户端契约接口:/api/v1/license/{verify,activate,deactivate,heartbeat}
- 定价订单:Plan / Order / 支付网关配置
- 防重复购买:CustomerEntitlement + 幂等支付 webhook + 手动发放
- 分析审计:Dashboard 统计 / Analytics / AuditLog / Setting 管理

【前端】
- Dashboard(ECharts 图表)、产品、客户、License、计划、订单、权益、日志、设置
- 9 个完整 CRUD 业务页面 + 登录/布局

【部署】
- SQLite + 单二进制(//go:embed 嵌入前端)
- 开发:./run.sh start(前端5181/后端9001)
- 生产:./run.sh build && ./run.sh binary start
- 默认账号:admin/admin

Author: Logan.Li
2026-08-07 15:02:00 +08:00

84 lines
3.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package model
import (
"time"
"gorm.io/gorm"
)
// License 期限常量(天数,0 表示永久) // Logan.Li
const (
Duration1Month = 30
Duration3Months = 90
Duration6Months = 180
Duration1Year = 365
Duration2Years = 730
Duration3Years = 1095
Duration5Years = 1825
DurationForever = 0
)
// License 状态常量 // Logan.Li
const (
LicenseStatusInactive = "inactive"
LicenseStatusActive = "active"
LicenseStatusExpired = "expired"
LicenseStatusRevoked = "revoked"
LicenseStatusSuspended = "suspended"
)
// PermanentEndDate 永久授权的到期时间(2099-12-31) // Logan.Li
var PermanentEndDate = time.Date(2099, 12, 31, 23, 59, 59, 0, time.UTC)
// License 许可证模型 // Logan.Li
type License struct {
ID uint `json:"id" gorm:"primaryKey"`
LicenseKey string `json:"license_key" gorm:"size:100;uniqueIndex;not null"`
CustomerID uint `json:"customer_id"`
Customer Customer `json:"customer,omitempty" gorm:"foreignKey:CustomerID"`
ProductID uint `json:"product_id"`
Product Product `json:"product,omitempty" gorm:"foreignKey:ProductID"`
Status string `json:"status" gorm:"size:20;default:'inactive'"`
StartDate time.Time `json:"start_date"`
EndDate time.Time `json:"end_date"`
Duration int `json:"duration" gorm:"default:365"` // 天数,0 表示永久
MaxActivations int `json:"max_activations" gorm:"default:1"`
CurrentActivations int `json:"current_activations" gorm:"default:0"`
IsTrial bool `json:"is_trial" gorm:"default:false"`
TrialDays int `json:"trial_days" gorm:"default:0"`
RevokeReason string `json:"revoke_reason" gorm:"type:text"`
Notes string `json:"notes" gorm:"type:text"`
Activations []Activation `json:"activations,omitempty" gorm:"foreignKey:LicenseID"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"deleted_at,omitempty" gorm:"index"`
}
// TableName 指定表名 // Logan.Li
func (License) TableName() string {
return "licenses"
}
// Activation 激活记录模型(机器绑定) // Logan.Li
type Activation struct {
ID uint `json:"id" gorm:"primaryKey"`
LicenseID uint `json:"license_id"`
License License `json:"license,omitempty" gorm:"foreignKey:LicenseID"`
DeviceID string `json:"device_id" gorm:"size:100"`
DeviceName string `json:"device_name" gorm:"size:200"`
DeviceInfo string `json:"device_info" gorm:"type:text"` // JSON 格式存储设备信息
IP string `json:"ip" gorm:"size:50"`
Status string `json:"status" gorm:"size:20;default:'active'"` // active / inactive
IsOnline bool `json:"is_online" gorm:"default:false"`
ActivatedAt time.Time `json:"activated_at"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
LastSeenAt time.Time `json:"last_seen_at"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// TableName 指定表名 // Logan.Li
func (Activation) TableName() string {
return "activations"
}