231 lines
5.7 KiB
Go
231 lines
5.7 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"license-manager/internal/models"
|
|
"license-manager/internal/repository"
|
|
pkgcontext "license-manager/pkg/context"
|
|
"license-manager/pkg/i18n"
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// PackageService 套餐服务接口
|
|
type PackageService interface {
|
|
// 管理端接口
|
|
CreatePackage(ctx context.Context, req *models.PackageCreateRequest) (*models.Package, error)
|
|
UpdatePackage(ctx context.Context, id string, req *models.PackageUpdateRequest) (*models.Package, error)
|
|
DeletePackage(ctx context.Context, id string) error
|
|
GetPackageList(ctx context.Context, req *models.PackageListRequest) (*models.PackageListResponse, error)
|
|
GetPackageDetail(ctx context.Context, id string) (*models.Package, error)
|
|
|
|
// 用户端接口
|
|
GetCuPackageList(ctx context.Context) ([]*models.CuPackageResponse, error)
|
|
}
|
|
|
|
type packageService struct {
|
|
repo repository.PackageRepository
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewPackageService 创建套餐服务
|
|
func NewPackageService(repo repository.PackageRepository, db *gorm.DB) PackageService {
|
|
return &packageService{
|
|
repo: repo,
|
|
db: db,
|
|
}
|
|
}
|
|
|
|
// ========== 管理端接口实现 ==========
|
|
|
|
func (s *packageService) CreatePackage(ctx context.Context, req *models.PackageCreateRequest) (*models.Package, error) {
|
|
lang := pkgcontext.GetLanguageFromContext(ctx)
|
|
|
|
pkg := &models.Package{
|
|
Name: req.Name,
|
|
Type: req.Type,
|
|
Price: req.Price,
|
|
PriceDescription: req.PriceDescription,
|
|
DurationDescription: req.DurationDescription,
|
|
Description: req.Description,
|
|
Features: req.Features,
|
|
Status: req.Status,
|
|
SortOrder: req.SortOrder,
|
|
Remark: req.Remark,
|
|
}
|
|
|
|
if err := s.repo.Create(pkg); err != nil {
|
|
return nil, i18n.NewI18nError("800001", lang)
|
|
}
|
|
|
|
return pkg, nil
|
|
}
|
|
|
|
func (s *packageService) UpdatePackage(ctx context.Context, id string, req *models.PackageUpdateRequest) (*models.Package, error) {
|
|
lang := pkgcontext.GetLanguageFromContext(ctx)
|
|
|
|
pkg, err := s.repo.GetByID(id)
|
|
if err != nil {
|
|
return nil, i18n.NewI18nError("800002", lang)
|
|
}
|
|
|
|
// 更新字段
|
|
if req.Name != "" {
|
|
pkg.Name = req.Name
|
|
}
|
|
if req.Type != "" {
|
|
pkg.Type = req.Type
|
|
}
|
|
if req.Price >= 0 {
|
|
pkg.Price = req.Price
|
|
}
|
|
if req.PriceDescription != "" {
|
|
pkg.PriceDescription = req.PriceDescription
|
|
}
|
|
if req.DurationDescription != "" {
|
|
pkg.DurationDescription = req.DurationDescription
|
|
}
|
|
if req.Description != "" {
|
|
pkg.Description = req.Description
|
|
}
|
|
if req.Features != "" {
|
|
pkg.Features = req.Features
|
|
}
|
|
if req.Status != nil {
|
|
pkg.Status = *req.Status
|
|
}
|
|
if req.SortOrder != nil {
|
|
pkg.SortOrder = *req.SortOrder
|
|
}
|
|
if req.Remark != "" {
|
|
pkg.Remark = req.Remark
|
|
}
|
|
|
|
pkg.UpdatedAt = time.Now()
|
|
|
|
if err := s.repo.Update(pkg); err != nil {
|
|
return nil, i18n.NewI18nError("800003", lang)
|
|
}
|
|
|
|
return pkg, nil
|
|
}
|
|
|
|
func (s *packageService) DeletePackage(ctx context.Context, id string) error {
|
|
lang := pkgcontext.GetLanguageFromContext(ctx)
|
|
|
|
// 检查是否存在
|
|
_, err := s.repo.GetByID(id)
|
|
if err != nil {
|
|
return i18n.NewI18nError("800002", lang)
|
|
}
|
|
|
|
if err := s.repo.Delete(id); err != nil {
|
|
return i18n.NewI18nError("800004", lang)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *packageService) GetPackageList(ctx context.Context, req *models.PackageListRequest) (*models.PackageListResponse, error) {
|
|
packages, total, err := s.repo.GetList(ctx, req)
|
|
if err != nil {
|
|
lang := pkgcontext.GetLanguageFromContext(ctx)
|
|
return nil, i18n.NewI18nError("800005", lang)
|
|
}
|
|
|
|
responses := make([]*models.PackageResponse, len(packages))
|
|
for i, pkg := range packages {
|
|
responses[i] = pkg.ToResponse()
|
|
}
|
|
|
|
return &models.PackageListResponse{
|
|
Packages: responses,
|
|
TotalCount: total,
|
|
}, nil
|
|
}
|
|
|
|
func (s *packageService) GetPackageDetail(ctx context.Context, id string) (*models.Package, error) {
|
|
lang := pkgcontext.GetLanguageFromContext(ctx)
|
|
|
|
pkg, err := s.repo.GetByID(id)
|
|
if err != nil {
|
|
return nil, i18n.NewI18nError("800002", lang)
|
|
}
|
|
|
|
return pkg, nil
|
|
}
|
|
|
|
// ========== 用户端接口实现 ==========
|
|
|
|
func (s *packageService) GetCuPackageList(ctx context.Context) ([]*models.CuPackageResponse, error) {
|
|
packages, err := s.repo.GetEnabledList(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
responses := make([]*models.CuPackageResponse, len(packages))
|
|
for i, pkg := range packages {
|
|
responses[i] = s.toCuPackageResponse(pkg)
|
|
}
|
|
|
|
return responses, nil
|
|
}
|
|
|
|
// toCuPackageResponse 转换为用户端套餐响应(兼容原有结构)
|
|
func (s *packageService) toCuPackageResponse(pkg *models.Package) *models.CuPackageResponse {
|
|
// 从features中解析max_devices
|
|
maxDevices := 1000 // 默认值
|
|
if pkg.Features != "" {
|
|
var features []string
|
|
if err := json.Unmarshal([]byte(pkg.Features), &features); err == nil {
|
|
for _, f := range features {
|
|
// 尝试解析"X个许可"格式
|
|
var n int
|
|
if _, err := fmt.Sscanf(f, "%d个许可", &n); err == nil {
|
|
maxDevices = n
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 构建details字符串
|
|
details := pkg.Description
|
|
if pkg.DurationDescription != "" {
|
|
if details != "" {
|
|
details += "|"
|
|
}
|
|
details += pkg.DurationDescription
|
|
}
|
|
if maxDevices > 0 {
|
|
if details != "" {
|
|
details += "|"
|
|
}
|
|
details += fmt.Sprintf("%d个许可", maxDevices)
|
|
}
|
|
|
|
// 计算 display_price
|
|
displayPrice := ""
|
|
if pkg.Price != 0 {
|
|
displayPrice = fmt.Sprintf("¥%g", pkg.Price)
|
|
} else {
|
|
displayPrice = pkg.PriceDescription
|
|
}
|
|
|
|
return &models.CuPackageResponse{
|
|
ID: pkg.ID,
|
|
Name: pkg.Name,
|
|
Type: pkg.Type,
|
|
Price: pkg.Price,
|
|
DisplayPrice: displayPrice,
|
|
PriceDescription: pkg.PriceDescription,
|
|
MaxDevices: maxDevices,
|
|
Description: pkg.Description,
|
|
Features: pkg.Features,
|
|
Details: details,
|
|
}
|
|
}
|