Files
opsx-licence/backend/database/seed.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

155 lines
4.3 KiB
Go

package database
import (
"backend/internal/model"
"backend/utils"
"log"
"time"
"gorm.io/gorm"
)
const (
defaultAdminUsername = "admin"
defaultAdminPassword = "admin"
)
// SeedDefaults 初始化默认数据:管理员账号 + 系统设置 + 示例业务数据 // Logan.Li
func SeedDefaults(db *gorm.DB) error {
if err := seedAdmin(db); err != nil {
return err
}
if err := seedSetting(db); err != nil {
return err
}
if err := seedSampleData(db); err != nil {
return err
}
return nil
}
// seedAdmin 初始化默认管理员账号(仅在不存在时创建) // Logan.Li
func seedAdmin(db *gorm.DB) error {
var count int64
db.Model(&model.User{}).Where("username = ?", defaultAdminUsername).Count(&count)
if count > 0 {
return nil
}
admin := model.User{
Username: defaultAdminUsername,
Password: utils.HashPassword(defaultAdminPassword),
Email: "admin@opsx-licence.local",
Role: "admin",
IsActive: true,
}
if err := db.Create(&admin).Error; err != nil {
return err
}
log.Printf("[初始化] 已创建默认管理员账号: %s / %s(请尽快修改密码)", defaultAdminUsername, defaultAdminPassword)
return nil
}
// seedSetting 初始化默认系统设置(仅创建一次) // Logan.Li
func seedSetting(db *gorm.DB) error {
var count int64
db.Model(&model.Setting{}).Count(&count)
if count > 0 {
return nil
}
setting := model.Setting{
SystemName: "opsx-licence",
DefaultDuration: 365,
DefaultMaxActivations: 1,
ExpireReminderDays: 7,
APIRateLimit: 1000,
LogRetentionDays: 365,
}
if err := db.Create(&setting).Error; err != nil {
return err
}
log.Println("[初始化] 已创建默认系统设置")
return nil
}
// seedSampleData 初始化示例业务数据(产品/客户/计划/支付网关),便于开发联调 // Logan.Li
func seedSampleData(db *gorm.DB) error {
var productCount int64
db.Model(&model.Product{}).Count(&productCount)
if productCount > 0 {
return nil
}
// 示例产品 // Logan.Li
product := model.Product{
Name: "OpsX Tools Suite",
Code: "opsx-tools",
Version: "1.0.0",
Description: "OpsX 工具集 - 一站式运维工具箱",
Features: `["CLI","GUI","Web Console","API"]`,
Price: 99.00,
PriceModel: "subscription",
Status: 1,
}
if err := db.Create(&product).Error; err != nil {
return err
}
// 示例客户 // Logan.Li
customer := model.Customer{
Name: "示例客户",
Company: "Acme Inc.",
Email: "demo@acme.com",
Phone: "13800000000",
Status: 1,
}
if err := db.Create(&customer).Error; err != nil {
return err
}
// 示例定价计划(买断 + 月订阅 + 年订阅) // Logan.Li
plans := []model.Plan{
{ProductID: product.ID, Name: "个人永久版", PlanType: "perpetual", Price: 199, Currency: "USD", Duration: 0, MaxDevices: 1, Features: `["全部功能","永久使用","1 设备"]`, SortOrder: 1, Status: 1},
{ProductID: product.ID, Name: "专业版(月)", PlanType: "monthly", Price: 19, Currency: "USD", Duration: 30, MaxDevices: 3, Features: `["全部功能","按月订阅","3 设备"]`, SortOrder: 2, Status: 1},
{ProductID: product.ID, Name: "企业版(年)", PlanType: "yearly", Price: 199, Currency: "USD", Duration: 365, MaxDevices: 10, Features: `["全部功能","按年订阅优惠","10 设备","优先支持"]`, SortOrder: 3, Status: 1},
}
for i := range plans {
if err := db.Create(&plans[i]).Error; err != nil {
return err
}
}
// 示例 License // Logan.Li
now := time.Now()
license := model.License{
LicenseKey: utils.GenerateLicenseKey(),
CustomerID: customer.ID,
ProductID: product.ID,
Status: model.LicenseStatusActive,
StartDate: now,
EndDate: now.AddDate(0, 0, 365),
Duration: 365,
MaxActivations: 3,
Notes: "示例授权,初始化生成",
}
if err := db.Create(&license).Error; err != nil {
return err
}
// 示例支付网关配置(沙箱) // Logan.Li
gateway := model.PaymentGatewayConfig{
Gateway: "creem",
Enabled: true,
SandboxMode: true,
Currency: "USD",
Priority: 1,
}
if err := db.Create(&gateway).Error; err != nil {
return err
}
log.Println("[初始化] 已创建示例产品、客户、计划、License、支付网关")
return nil
}