feat(*): 功能开放与页面布局 - 新增运维开关并优化后台及创作界面空间利用
This commit is contained in:
1 parent
8f7c492b70
commit
f439d600ba
36 files changed
+723
-86
No files matched your search
@@ -0,0 +1,139 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"infinite-canvas/backend/internal/model"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const featureAvailabilitySettingKey = "feature_availability"
|
||||
|
||||
const (
|
||||
FeatureShortDrama = "shortDrama"
|
||||
FeatureTaskCenter = "taskCenter"
|
||||
FeatureCredits = "credits"
|
||||
)
|
||||
|
||||
type FeatureAvailability struct {
|
||||
ShortDramaEnabled bool `json:"shortDramaEnabled"`
|
||||
TaskCenterEnabled bool `json:"taskCenterEnabled"`
|
||||
CreditsEnabled bool `json:"creditsEnabled"`
|
||||
}
|
||||
|
||||
type PublicFeatureAvailability struct {
|
||||
FeatureAvailability
|
||||
Configured bool `json:"configured"`
|
||||
UpdatedBy string `json:"updatedBy,omitempty"`
|
||||
UpdatedAt time.Time `json:"updatedAt,omitempty"`
|
||||
}
|
||||
|
||||
func defaultFeatureAvailability() FeatureAvailability {
|
||||
// 缺少配置代表尚未由运维接管,默认保持现有功能全部开放。
|
||||
return FeatureAvailability{ShortDramaEnabled: true, TaskCenterEnabled: true, CreditsEnabled: true}
|
||||
}
|
||||
|
||||
func (s *Service) FeatureAvailability() (*PublicFeatureAvailability, error) {
|
||||
setting, value, err := s.readFeatureAvailability()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return publicFeatureAvailability(setting, value), nil
|
||||
}
|
||||
|
||||
func (s *Service) AdminFeatureAvailability(actor *model.User) (*PublicFeatureAvailability, error) {
|
||||
if err := s.RequireAdmin(actor); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.FeatureAvailability()
|
||||
}
|
||||
|
||||
func (s *Service) UpdateFeatureAvailability(actor *model.User, value FeatureAvailability) (*PublicFeatureAvailability, error) {
|
||||
if err := s.RequireAdmin(actor); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
current, before, err := s.readFeatureAvailability()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
encoded, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
setting := model.SystemSetting{Key: featureAvailabilitySettingKey, ValueJSON: string(encoded), UpdatedBy: actor.ID}
|
||||
if current != nil {
|
||||
setting.CreatedAt = current.CreatedAt
|
||||
}
|
||||
if err := s.repo.SaveSystemSetting(&setting); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := s.appendAdminAudit(actor, "feature_availability.update", "system_setting", featureAvailabilitySettingKey, "更新功能开放配置", map[string]any{"before": before, "after": value}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return publicFeatureAvailability(&setting, value), nil
|
||||
}
|
||||
|
||||
func (s *Service) FeatureEnabled(feature string) (bool, error) {
|
||||
_, value, err := s.readFeatureAvailability()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
switch feature {
|
||||
case FeatureShortDrama:
|
||||
return value.ShortDramaEnabled, nil
|
||||
case FeatureTaskCenter:
|
||||
return value.TaskCenterEnabled, nil
|
||||
case FeatureCredits:
|
||||
return value.CreditsEnabled, nil
|
||||
default:
|
||||
return false, errors.New("未知功能开放配置")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) RequireFeature(feature string) error {
|
||||
enabled, err := s.FeatureEnabled(feature)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if enabled {
|
||||
return nil
|
||||
}
|
||||
switch feature {
|
||||
case FeatureShortDrama:
|
||||
return Forbidden("短剧创作暂未开放")
|
||||
case FeatureTaskCenter:
|
||||
return Forbidden("任务中心暂未开放")
|
||||
case FeatureCredits:
|
||||
return Forbidden("积分功能暂未开放")
|
||||
default:
|
||||
return Forbidden("该功能暂未开放")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) readFeatureAvailability() (*model.SystemSetting, FeatureAvailability, error) {
|
||||
setting, err := s.repo.SystemSetting(featureAvailabilitySettingKey)
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, defaultFeatureAvailability(), nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, FeatureAvailability{}, err
|
||||
}
|
||||
value := FeatureAvailability{}
|
||||
if strings.TrimSpace(setting.ValueJSON) == "" || json.Unmarshal([]byte(setting.ValueJSON), &value) != nil {
|
||||
return nil, FeatureAvailability{}, errors.New("功能开放配置格式无效")
|
||||
}
|
||||
return setting, value, nil
|
||||
}
|
||||
|
||||
func publicFeatureAvailability(setting *model.SystemSetting, value FeatureAvailability) *PublicFeatureAvailability {
|
||||
result := &PublicFeatureAvailability{FeatureAvailability: value, Configured: setting != nil}
|
||||
if setting != nil {
|
||||
result.UpdatedBy = setting.UpdatedBy
|
||||
result.UpdatedAt = setting.UpdatedAt
|
||||
}
|
||||
return result
|
||||
}
|
||||
Reference in new issue
Block a user