feat():learning后台管理项目初始化
This commit is contained in:
403
internal/api/handlers/vm_pricing_handler.go
Normal file
403
internal/api/handlers/vm_pricing_handler.go
Normal file
@@ -0,0 +1,403 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"goalfymax-admin/pkg/utils"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// VmPricingHandler 虚拟机价格配置处理器
|
||||
type VmPricingHandler struct {
|
||||
db *gorm.DB
|
||||
response *utils.Response
|
||||
}
|
||||
|
||||
// NewVmPricingHandler 创建处理器
|
||||
func NewVmPricingHandler(db *gorm.DB) *VmPricingHandler {
|
||||
return &VmPricingHandler{
|
||||
db: db,
|
||||
response: utils.NewResponse(),
|
||||
}
|
||||
}
|
||||
|
||||
// VmSpecResponse 虚拟机规格响应
|
||||
type VmSpecResponse struct {
|
||||
ID uint `json:"id"`
|
||||
SpecType string `json:"spec_type"`
|
||||
CPUCores int `json:"cpu_cores"`
|
||||
MemoryGB int `json:"memory_gb"`
|
||||
Description *string `json:"description"`
|
||||
CostPricePerMinute float64 `json:"cost_price_per_minute"`
|
||||
MarkupRate float64 `json:"markup_rate"`
|
||||
IsActive bool `json:"is_active"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
||||
|
||||
// VmTemplateResponse 虚拟机模板响应
|
||||
type VmTemplateResponse struct {
|
||||
ID uint `json:"id"`
|
||||
SpecType string `json:"spec_type"`
|
||||
TemplateID string `json:"template_id"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
||||
|
||||
// VmSpecCreateRequest 规格创建请求
|
||||
type VmSpecCreateRequest struct {
|
||||
SpecType string `json:"spec_type" binding:"required"`
|
||||
CPUCores int `json:"cpu_cores" binding:"required"`
|
||||
MemoryGB int `json:"memory_gb" binding:"required"`
|
||||
Description *string `json:"description"`
|
||||
CostPricePerMinute float64 `json:"cost_price_per_minute" binding:"required"`
|
||||
MarkupRate *float64 `json:"markup_rate"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
}
|
||||
|
||||
// VmSpecUpdateRequest 规格更新请求
|
||||
type VmSpecUpdateRequest struct {
|
||||
CostPricePerMinute *float64 `json:"cost_price_per_minute"`
|
||||
MarkupRate *float64 `json:"markup_rate"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
}
|
||||
|
||||
// VmTemplateCreateRequest 模板创建请求
|
||||
type VmTemplateCreateRequest struct {
|
||||
SpecType string `json:"spec_type" binding:"required"`
|
||||
TemplateID string `json:"template_id" binding:"required"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
}
|
||||
|
||||
// VmTemplateUpdateRequest 模板更新请求
|
||||
type VmTemplateUpdateRequest struct {
|
||||
IsDefault *bool `json:"is_default"`
|
||||
}
|
||||
|
||||
// GetVmSpecs 获取虚拟机规格列表
|
||||
func (h *VmPricingHandler) GetVmSpecs(c *gin.Context) {
|
||||
var specs []VmSpecResponse
|
||||
|
||||
// 构建查询条件
|
||||
query := h.db.Table("sb_sandbox_specs")
|
||||
|
||||
// 添加筛选条件
|
||||
if specType := c.Query("spec_type"); specType != "" {
|
||||
query = query.Where("spec_type LIKE ?", "%"+specType+"%")
|
||||
}
|
||||
if status := c.Query("status"); status != "" {
|
||||
if status == "active" {
|
||||
query = query.Where("is_active = ?", true)
|
||||
} else if status == "inactive" {
|
||||
query = query.Where("is_active = ?", false)
|
||||
}
|
||||
}
|
||||
|
||||
// 分页
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
size, _ := strconv.Atoi(c.DefaultQuery("size", "10"))
|
||||
offset := (page - 1) * size
|
||||
|
||||
// 先获取总数
|
||||
var total int64
|
||||
err := query.Count(&total).Error
|
||||
if err != nil {
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 然后获取分页数据
|
||||
err = query.Order("created_at DESC").Offset(offset).Limit(size).Find(&specs).Error
|
||||
if err != nil {
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.response.Page(c, specs, total, page, size)
|
||||
}
|
||||
|
||||
// UpdateVmSpec 更新虚拟机规格
|
||||
func (h *VmPricingHandler) UpdateVmSpec(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
var req VmSpecUpdateRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
h.response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 构建更新字段
|
||||
updates := make(map[string]interface{})
|
||||
if req.CostPricePerMinute != nil {
|
||||
updates["cost_price_per_minute"] = *req.CostPricePerMinute
|
||||
}
|
||||
if req.MarkupRate != nil {
|
||||
updates["markup_rate"] = *req.MarkupRate
|
||||
}
|
||||
if req.IsActive != nil {
|
||||
updates["is_active"] = *req.IsActive
|
||||
}
|
||||
|
||||
if len(updates) == 0 {
|
||||
h.response.BadRequest(c, "没有需要更新的字段")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查规格是否存在
|
||||
var count int64
|
||||
err := h.db.Table("sb_sandbox_specs").Where("id = ?", id).Count(&count).Error
|
||||
if err != nil {
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
h.response.NotFound(c, "规格不存在")
|
||||
return
|
||||
}
|
||||
|
||||
// 更新规格
|
||||
err = h.db.Table("sb_sandbox_specs").Where("id = ?", id).Updates(updates).Error
|
||||
if err != nil {
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.response.Success(c, "规格更新成功")
|
||||
}
|
||||
|
||||
// DeleteVmSpec 删除虚拟机规格
|
||||
func (h *VmPricingHandler) DeleteVmSpec(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
// 检查规格是否存在
|
||||
var count int64
|
||||
err := h.db.Table("sb_sandbox_specs").Where("id = ?", id).Count(&count).Error
|
||||
if err != nil {
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
h.response.NotFound(c, "规格不存在")
|
||||
return
|
||||
}
|
||||
|
||||
// 删除规格
|
||||
err = h.db.Table("sb_sandbox_specs").Where("id = ?", id).Delete(nil).Error
|
||||
if err != nil {
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.response.Success(c, "规格删除成功")
|
||||
}
|
||||
|
||||
// CreateVmSpec 创建虚拟机规格
|
||||
func (h *VmPricingHandler) CreateVmSpec(c *gin.Context) {
|
||||
var req VmSpecCreateRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
h.response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 检查规格类型是否已存在
|
||||
var count int64
|
||||
err := h.db.Table("sb_sandbox_specs").Where("spec_type = ?", req.SpecType).Count(&count).Error
|
||||
if err != nil {
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
if count > 0 {
|
||||
h.response.BadRequest(c, "该配置类型已存在")
|
||||
return
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
markupRate := 0.3000 // 默认30%
|
||||
if req.MarkupRate != nil {
|
||||
markupRate = *req.MarkupRate
|
||||
}
|
||||
isActive := true
|
||||
if req.IsActive != nil {
|
||||
isActive = *req.IsActive
|
||||
}
|
||||
|
||||
// 创建规格
|
||||
insertData := map[string]interface{}{
|
||||
"spec_type": req.SpecType,
|
||||
"cpu_cores": req.CPUCores,
|
||||
"memory_gb": req.MemoryGB,
|
||||
"cost_price_per_minute": req.CostPricePerMinute,
|
||||
"markup_rate": markupRate,
|
||||
"is_active": isActive,
|
||||
}
|
||||
if req.Description != nil {
|
||||
insertData["description"] = *req.Description
|
||||
}
|
||||
|
||||
err = h.db.Table("sb_sandbox_specs").Create(insertData).Error
|
||||
if err != nil {
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.response.Success(c, "规格创建成功")
|
||||
}
|
||||
|
||||
// GetVmTemplates 获取虚拟机模板列表
|
||||
func (h *VmPricingHandler) GetVmTemplates(c *gin.Context) {
|
||||
var templates []VmTemplateResponse
|
||||
|
||||
// 构建查询条件
|
||||
query := h.db.Table("sb_sandbox_templates")
|
||||
|
||||
// 添加筛选条件
|
||||
if specType := c.Query("spec_type"); specType != "" {
|
||||
query = query.Where("spec_type = ?", specType)
|
||||
}
|
||||
|
||||
// 分页
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
size, _ := strconv.Atoi(c.DefaultQuery("size", "10"))
|
||||
offset := (page - 1) * size
|
||||
|
||||
// 先获取总数
|
||||
var total int64
|
||||
err := query.Count(&total).Error
|
||||
if err != nil {
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 然后获取分页数据
|
||||
err = query.Order("spec_type ASC, created_at DESC").Offset(offset).Limit(size).Find(&templates).Error
|
||||
if err != nil {
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.response.Page(c, templates, total, page, size)
|
||||
}
|
||||
|
||||
// CreateVmTemplate 创建虚拟机模板
|
||||
func (h *VmPricingHandler) CreateVmTemplate(c *gin.Context) {
|
||||
var req VmTemplateCreateRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
h.response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 检查规格是否存在
|
||||
var specCount int64
|
||||
err := h.db.Table("sb_sandbox_specs").Where("spec_type = ?", req.SpecType).Count(&specCount).Error
|
||||
if err != nil {
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
if specCount == 0 {
|
||||
h.response.BadRequest(c, "规格类型不存在")
|
||||
return
|
||||
}
|
||||
|
||||
// 如果设置为默认模板,需要先取消同规格的其他默认模板
|
||||
if req.IsDefault {
|
||||
err = h.db.Table("sb_sandbox_templates").
|
||||
Where("spec_type = ? AND is_default = ?", req.SpecType, true).
|
||||
Update("is_default", false).Error
|
||||
if err != nil {
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否已存在相同的规格-模板组合
|
||||
var existingCount int64
|
||||
err = h.db.Table("sb_sandbox_templates").
|
||||
Where("spec_type = ? AND template_id = ?", req.SpecType, req.TemplateID).
|
||||
Count(&existingCount).Error
|
||||
if err != nil {
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
if existingCount > 0 {
|
||||
h.response.BadRequest(c, "该规格和模板的组合已存在")
|
||||
return
|
||||
}
|
||||
|
||||
// 创建模板
|
||||
insertData := map[string]interface{}{
|
||||
"spec_type": req.SpecType,
|
||||
"template_id": req.TemplateID,
|
||||
"is_default": req.IsDefault,
|
||||
}
|
||||
err = h.db.Table("sb_sandbox_templates").Create(insertData).Error
|
||||
if err != nil {
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.response.Success(c, "模板创建成功")
|
||||
}
|
||||
|
||||
// DeleteVmTemplate 删除虚拟机模板
|
||||
func (h *VmPricingHandler) DeleteVmTemplate(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
// 检查模板是否存在
|
||||
var count int64
|
||||
err := h.db.Table("sb_sandbox_templates").Where("id = ?", id).Count(&count).Error
|
||||
if err != nil {
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
h.response.NotFound(c, "模板不存在")
|
||||
return
|
||||
}
|
||||
|
||||
// 删除模板
|
||||
err = h.db.Table("sb_sandbox_templates").Where("id = ?", id).Delete(nil).Error
|
||||
if err != nil {
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.response.Success(c, "模板删除成功")
|
||||
}
|
||||
|
||||
// SetDefaultVmTemplate 设置默认模板
|
||||
func (h *VmPricingHandler) SetDefaultVmTemplate(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
// 获取模板信息
|
||||
var template VmTemplateResponse
|
||||
err := h.db.Table("sb_sandbox_templates").Where("id = ?", id).First(&template).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
h.response.NotFound(c, "模板不存在")
|
||||
return
|
||||
}
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 取消同规格的其他默认模板
|
||||
err = h.db.Table("sb_sandbox_templates").
|
||||
Where("spec_type = ? AND is_default = ? AND id != ?", template.SpecType, true, id).
|
||||
Update("is_default", false).Error
|
||||
if err != nil {
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 设置当前模板为默认
|
||||
err = h.db.Table("sb_sandbox_templates").Where("id = ?", id).Update("is_default", true).Error
|
||||
if err != nil {
|
||||
h.response.InternalServerError(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
h.response.Success(c, "默认模板设置成功")
|
||||
}
|
||||
Reference in New Issue
Block a user