feat(subscribe): add Language field to subscription models and update query logic

This commit is contained in:
Chang lue Tsen
2025-09-03 15:44:04 -04:00
parent f8e6cf515e
commit f632ea2c89
24 changed files with 75 additions and 259 deletions
@@ -1,18 +0,0 @@
package system
import (
"github.com/gin-gonic/gin"
"github.com/perfect-panel/server/internal/logic/admin/system"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/pkg/result"
)
// Get subscribe type
func GetSubscribeTypeHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
return func(c *gin.Context) {
l := system.NewGetSubscribeTypeLogic(c.Request.Context(), svcCtx)
resp, err := l.GetSubscribeType()
result.HttpResult(c, resp, err)
}
}
@@ -4,15 +4,23 @@ import (
"github.com/gin-gonic/gin"
"github.com/perfect-panel/server/internal/logic/public/subscribe"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/result"
)
// Get subscribe list
// QuerySubscribeListHandler Get subscribe list
func QuerySubscribeListHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
return func(c *gin.Context) {
var req types.QuerySubscribeListRequest
_ = c.ShouldBind(&req)
validateErr := svcCtx.Validate(&req)
if validateErr != nil {
result.ParamErrorResult(c, validateErr)
return
}
l := subscribe.NewQuerySubscribeListLogic(c.Request.Context(), svcCtx)
resp, err := l.QuerySubscribeList()
resp, err := l.QuerySubscribeList(&req)
result.HttpResult(c, resp, err)
}
}
-6
View File
@@ -435,9 +435,6 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
// Update subscribe config
adminSystemGroupRouter.PUT("/subscribe_config", adminSystem.UpdateSubscribeConfigHandler(serverCtx))
// Get subscribe type
adminSystemGroupRouter.GET("/subscribe_type", adminSystem.GetSubscribeTypeHandler(serverCtx))
// Get Team of Service Config
adminSystemGroupRouter.GET("/tos_config", adminSystem.GetTosConfigHandler(serverCtx))
@@ -722,9 +719,6 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
publicSubscribeGroupRouter.Use(middleware.AuthMiddleware(serverCtx))
{
// Get subscribe group list
publicSubscribeGroupRouter.GET("/group/list", publicSubscribe.QuerySubscribeGroupListHandler(serverCtx))
// Get subscribe list
publicSubscribeGroupRouter.GET("/list", publicSubscribe.QuerySubscribeListHandler(serverCtx))
}
@@ -37,6 +37,7 @@ func (l *CreateSubscribeLogic) CreateSubscribe(req *types.CreateSubscribeRequest
sub := &subscribe.Subscribe{
Id: 0,
Name: req.Name,
Language: req.Language,
Description: req.Description,
UnitPrice: req.UnitPrice,
UnitTime: req.UnitTime,
@@ -47,7 +48,6 @@ func (l *CreateSubscribeLogic) CreateSubscribe(req *types.CreateSubscribeRequest
SpeedLimit: req.SpeedLimit,
DeviceLimit: req.DeviceLimit,
Quota: req.Quota,
GroupId: req.GroupId,
Nodes: tool.Int64SliceToString(req.Nodes),
NodeTags: tool.StringSliceToString(req.NodeTags),
Show: req.Show,
@@ -29,7 +29,7 @@ func NewGetSubscribeListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *
}
func (l *GetSubscribeListLogic) GetSubscribeList(req *types.GetSubscribeListRequest) (resp *types.GetSubscribeListResponse, err error) {
total, list, err := l.svcCtx.SubscribeModel.QuerySubscribeListByPage(l.ctx, int(req.Page), int(req.Size), req.GroupId, req.Search)
total, list, err := l.svcCtx.SubscribeModel.QuerySubscribeListByPage(l.ctx, int(req.Page), int(req.Size), req.Language, req.Search)
if err != nil {
l.Logger.Error("[GetSubscribeListLogic] get subscribe list failed: ", logger.Field("error", err.Error()))
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "get subscribe list failed: %v", err.Error())
@@ -45,6 +45,7 @@ func (l *UpdateSubscribeLogic) UpdateSubscribe(req *types.UpdateSubscribeRequest
sub := &subscribe.Subscribe{
Id: req.Id,
Name: req.Name,
Language: req.Language,
Description: req.Description,
UnitPrice: req.UnitPrice,
UnitTime: req.UnitTime,
@@ -55,7 +56,6 @@ func (l *UpdateSubscribeLogic) UpdateSubscribe(req *types.UpdateSubscribeRequest
SpeedLimit: req.SpeedLimit,
DeviceLimit: req.DeviceLimit,
Quota: req.Quota,
GroupId: req.GroupId,
Nodes: tool.Int64SliceToString(req.Nodes),
NodeTags: tool.StringSliceToString(req.NodeTags),
Show: req.Show,
@@ -1,42 +0,0 @@
package system
import (
"context"
"github.com/perfect-panel/server/internal/model/subscribeType"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/logger"
"github.com/perfect-panel/server/pkg/xerr"
"github.com/pkg/errors"
)
type GetSubscribeTypeLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logger.Logger
}
func NewGetSubscribeTypeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetSubscribeTypeLogic {
return &GetSubscribeTypeLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logger.WithContext(ctx),
}
}
func (l *GetSubscribeTypeLogic) GetSubscribeType() (resp *types.SubscribeType, err error) {
var list []*subscribeType.SubscribeType
err = l.svcCtx.DB.Model(&subscribeType.SubscribeType{}).Find(&list).Error
if err != nil {
l.Errorw("[GetSubscribeType] get subscribe type failed", logger.Field("error", err.Error()))
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "get subscribe type failed: %v", err)
}
typeList := make([]string, 0)
for _, item := range list {
typeList = append(typeList, item.Name)
}
return &types.SubscribeType{
SubscribeTypes: typeList,
}, nil
}
@@ -27,13 +27,22 @@ func NewQuerySubscribeListLogic(ctx context.Context, svcCtx *svc.ServiceContext)
}
}
func (l *QuerySubscribeListLogic) QuerySubscribeList() (resp *types.QuerySubscribeListResponse, err error) {
func (l *QuerySubscribeListLogic) QuerySubscribeList(req *types.QuerySubscribeListRequest) (resp *types.QuerySubscribeListResponse, err error) {
data, err := l.svcCtx.SubscribeModel.QuerySubscribeList(l.ctx)
total, data, err := l.svcCtx.SubscribeModel.QuerySubscribeListByPage(l.ctx, 1, 1000, req.Language, "")
if err != nil {
l.Errorw("[QuerySubscribeListLogic] Database Error", logger.Field("error", err.Error()))
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "QuerySubscribeList error: %v", err.Error())
}
// If no data is found for the specified language, query default language data
if total == 0 && req.Language != "" {
total, data, err = l.svcCtx.SubscribeModel.QuerySubscribeListByPage(l.ctx, 1, 1000, "", "")
if err != nil {
l.Errorw("[QuerySubscribeListLogic] Database Error", logger.Field("error", err.Error()))
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "QuerySubscribeList error: %v", err.Error())
}
}
resp = &types.QuerySubscribeListResponse{
Total: int64(len(data)),
}
+1
View File
@@ -26,6 +26,7 @@ type ServerFilter struct {
Size int
}
// Deprecated: use internal/model/node/server.go
type Server struct {
Id int64 `gorm:"primary_key"`
Name string `gorm:"type:varchar(100);not null;default:'';comment:Node Name"`
+6 -5
View File
@@ -8,7 +8,7 @@ import (
)
type customSubscribeLogicModel interface {
QuerySubscribeListByPage(ctx context.Context, page, size int, group int64, search string) (total int64, list []*Subscribe, err error)
QuerySubscribeListByPage(ctx context.Context, page, size int, lang string, search string) (total int64, list []*Subscribe, err error)
QuerySubscribeList(ctx context.Context) ([]*Subscribe, error)
QuerySubscribeListByShow(ctx context.Context) ([]*Subscribe, error)
QuerySubscribeIdsByNodeIdAndNodeTag(ctx context.Context, node []int64, tags []string) ([]*Subscribe, error)
@@ -25,7 +25,7 @@ func NewModel(conn *gorm.DB, c *redis.Client) Model {
}
// QuerySubscribeListByPage Get Subscribe List
func (m *customSubscribeModel) QuerySubscribeListByPage(ctx context.Context, page, size int, group int64, search string) (total int64, list []*Subscribe, err error) {
func (m *customSubscribeModel) QuerySubscribeListByPage(ctx context.Context, page, size int, lang string, search string) (total int64, list []*Subscribe, err error) {
err = m.QueryNoCacheCtx(ctx, &list, func(conn *gorm.DB, v interface{}) error {
// About to be abandoned
_ = conn.Model(&Subscribe{}).
@@ -33,13 +33,14 @@ func (m *customSubscribeModel) QuerySubscribeListByPage(ctx context.Context, pag
Update("sort", gorm.Expr("id"))
conn = conn.Model(&Subscribe{})
if group > 0 {
conn = conn.Where("group_id = ?", group)
if lang != "" {
conn = conn.Where("`language` = ?", lang)
}
if search != "" {
conn = conn.Where("`name` like ? or `description` like ?", "%"+search+"%", "%"+search+"%")
}
return conn.Count(&total).Order("sort ASC").Limit(size).Offset((page - 1) * size).Find(v).Error
err = conn.Count(&total).Order("sort ASC").Limit(size).Offset((page - 1) * size).Find(v).Error
return nil
})
return total, list, err
}
+1 -1
View File
@@ -9,6 +9,7 @@ import (
type Subscribe struct {
Id int64 `gorm:"primaryKey"`
Name string `gorm:"type:varchar(255);not null;default:'';comment:Subscribe Name"`
Language string `gorm:"type:varchar(255);not null;default:'';comment:Language"`
Description string `gorm:"type:text;comment:Subscribe Description"`
UnitPrice int64 `gorm:"type:int;not null;default:0;comment:Unit Price"`
UnitTime string `gorm:"type:varchar(255);not null;default:'';comment:Unit Time"`
@@ -19,7 +20,6 @@ type Subscribe struct {
SpeedLimit int64 `gorm:"type:int;not null;default:0;comment:Speed Limit"`
DeviceLimit int64 `gorm:"type:int;not null;default:0;comment:Device Limit"`
Quota int64 `gorm:"type:int;not null;default:0;comment:Quota"`
GroupId int64 `gorm:"type:bigint;comment:Group Id"`
Nodes string `gorm:"type:varchar(255);comment:Node Ids"`
NodeTags string `gorm:"type:varchar(255);comment:Node Tags"`
Show *bool `gorm:"type:tinyint(1);not null;default:0;comment:Show portal page"`
-117
View File
@@ -1,117 +0,0 @@
package subscribeType
import (
"context"
"errors"
"fmt"
"github.com/perfect-panel/server/pkg/cache"
"github.com/redis/go-redis/v9"
"gorm.io/gorm"
)
var _ Model = (*customSubscribeTypeModel)(nil)
var (
cacheSubscribeTypeIdPrefix = "cache:subscribeType:id:"
)
type (
Model interface {
subscribeTypeModel
customSubscribeTypeLogicModel
}
subscribeTypeModel interface {
Insert(ctx context.Context, data *SubscribeType) error
FindOne(ctx context.Context, id int64) (*SubscribeType, error)
Update(ctx context.Context, data *SubscribeType) error
Delete(ctx context.Context, id int64) error
Transaction(ctx context.Context, fn func(db *gorm.DB) error) error
}
customSubscribeTypeModel struct {
*defaultSubscribeTypeModel
}
defaultSubscribeTypeModel struct {
cache.CachedConn
table string
}
)
func newSubscribeTypeModel(db *gorm.DB, c *redis.Client) *defaultSubscribeTypeModel {
return &defaultSubscribeTypeModel{
CachedConn: cache.NewConn(db, c),
table: "`SubscribeType`",
}
}
//nolint:unused
func (m *defaultSubscribeTypeModel) batchGetCacheKeys(SubscribeTypes ...*SubscribeType) []string {
var keys []string
for _, subscribeType := range SubscribeTypes {
keys = append(keys, m.getCacheKeys(subscribeType)...)
}
return keys
}
func (m *defaultSubscribeTypeModel) getCacheKeys(data *SubscribeType) []string {
if data == nil {
return []string{}
}
SubscribeTypeIdKey := fmt.Sprintf("%s%v", cacheSubscribeTypeIdPrefix, data.Id)
cacheKeys := []string{
SubscribeTypeIdKey,
}
return cacheKeys
}
func (m *defaultSubscribeTypeModel) Insert(ctx context.Context, data *SubscribeType) error {
err := m.ExecCtx(ctx, func(conn *gorm.DB) error {
return conn.Create(&data).Error
}, m.getCacheKeys(data)...)
return err
}
func (m *defaultSubscribeTypeModel) FindOne(ctx context.Context, id int64) (*SubscribeType, error) {
SubscribeTypeIdKey := fmt.Sprintf("%s%v", cacheSubscribeTypeIdPrefix, id)
var resp SubscribeType
err := m.QueryCtx(ctx, &resp, SubscribeTypeIdKey, func(conn *gorm.DB, v interface{}) error {
return conn.Model(&SubscribeType{}).Where("`id` = ?", id).First(&resp).Error
})
switch {
case err == nil:
return &resp, nil
default:
return nil, err
}
}
func (m *defaultSubscribeTypeModel) Update(ctx context.Context, data *SubscribeType) error {
old, err := m.FindOne(ctx, data.Id)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
err = m.ExecCtx(ctx, func(conn *gorm.DB) error {
db := conn
return db.Save(data).Error
}, m.getCacheKeys(old)...)
return err
}
func (m *defaultSubscribeTypeModel) Delete(ctx context.Context, id int64) error {
data, err := m.FindOne(ctx, id)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil
}
return err
}
err = m.ExecCtx(ctx, func(conn *gorm.DB) error {
db := conn
return db.Delete(&SubscribeType{}, id).Error
}, m.getCacheKeys(data)...)
return err
}
func (m *defaultSubscribeTypeModel) Transaction(ctx context.Context, fn func(db *gorm.DB) error) error {
return m.TransactCtx(ctx, fn)
}
-16
View File
@@ -1,16 +0,0 @@
package subscribeType
import (
"github.com/redis/go-redis/v9"
"gorm.io/gorm"
)
type customSubscribeTypeLogicModel interface {
}
// NewModel returns a model for the database table.
func NewModel(conn *gorm.DB, c *redis.Client) Model {
return &customSubscribeTypeModel{
defaultSubscribeTypeModel: newSubscribeTypeModel(conn, c),
}
}
@@ -1,15 +0,0 @@
package subscribeType
import "time"
type SubscribeType struct {
Id int64 `gorm:"primary_key"`
Name string `gorm:"type:varchar(50);default:'';not null;comment:订阅类型"`
Mark string `gorm:"type:varchar(255);default:'';not null;comment:订阅标识"`
CreatedAt time.Time `gorm:"<-:create;comment:创建时间"`
UpdatedAt time.Time `gorm:"comment:更新时间"`
}
func (SubscribeType) TableName() string {
return "subscribe_type"
}
+7 -9
View File
@@ -17,7 +17,6 @@ import (
"github.com/perfect-panel/server/internal/model/order"
"github.com/perfect-panel/server/internal/model/payment"
"github.com/perfect-panel/server/internal/model/subscribe"
"github.com/perfect-panel/server/internal/model/subscribeType"
"github.com/perfect-panel/server/internal/model/system"
"github.com/perfect-panel/server/internal/model/ticket"
"github.com/perfect-panel/server/internal/model/traffic"
@@ -47,14 +46,13 @@ type ServiceContext struct {
ClientModel client.Model
TicketModel ticket.Model
//ServerModel server.Model
SystemModel system.Model
CouponModel coupon.Model
PaymentModel payment.Model
DocumentModel document.Model
SubscribeModel subscribe.Model
TrafficLogModel traffic.Model
AnnouncementModel announcement.Model
SubscribeTypeModel subscribeType.Model
SystemModel system.Model
CouponModel coupon.Model
PaymentModel payment.Model
DocumentModel document.Model
SubscribeModel subscribe.Model
TrafficLogModel traffic.Model
AnnouncementModel announcement.Model
Restart func() error
TelegramBot *tgbotapi.BotAPI
+11 -7
View File
@@ -373,6 +373,7 @@ type CreateSubscribeGroupRequest struct {
type CreateSubscribeRequest struct {
Name string `json:"name" validate:"required"`
Language string `json:"language"`
Description string `json:"description"`
UnitPrice int64 `json:"unit_price"`
UnitTime string `json:"unit_time"`
@@ -383,7 +384,6 @@ type CreateSubscribeRequest struct {
SpeedLimit int64 `json:"speed_limit"`
DeviceLimit int64 `json:"device_limit"`
Quota int64 `json:"quota"`
GroupId int64 `json:"group_id"`
Nodes []int64 `json:"nodes"`
NodeTags []string `json:"node_tags"`
Show *bool `json:"show"`
@@ -944,10 +944,10 @@ type GetSubscribeGroupListResponse struct {
}
type GetSubscribeListRequest struct {
Page int64 `form:"page" validate:"required"`
Size int64 `form:"size" validate:"required"`
GroupId int64 `form:"group_id,omitempty"`
Search string `form:"search,omitempty"`
Page int64 `form:"page" validate:"required"`
Size int64 `form:"size" validate:"required"`
Language string `form:"language,omitempty"`
Search string `form:"search,omitempty"`
}
type GetSubscribeListResponse struct {
@@ -1522,6 +1522,10 @@ type QuerySubscribeGroupListResponse struct {
Total int64 `json:"total"`
}
type QuerySubscribeListRequest struct {
Language string `form:"language"`
}
type QuerySubscribeListResponse struct {
List []Subscribe `json:"list"`
Total int64 `json:"total"`
@@ -1847,6 +1851,7 @@ type StripePayment struct {
type Subscribe struct {
Id int64 `json:"id"`
Name string `json:"name"`
Language string `json:"language"`
Description string `json:"description"`
UnitPrice int64 `json:"unit_price"`
UnitTime string `json:"unit_time"`
@@ -1857,7 +1862,6 @@ type Subscribe struct {
SpeedLimit int64 `json:"speed_limit"`
DeviceLimit int64 `json:"device_limit"`
Quota int64 `json:"quota"`
GroupId int64 `json:"group_id"`
Nodes []int64 `json:"nodes"`
NodeTags []string `json:"node_tags"`
Show bool `json:"show"`
@@ -2217,6 +2221,7 @@ type UpdateSubscribeGroupRequest struct {
type UpdateSubscribeRequest struct {
Id int64 `json:"id" validate:"required"`
Name string `json:"name" validate:"required"`
Language string `json:"language"`
Description string `json:"description"`
UnitPrice int64 `json:"unit_price"`
UnitTime string `json:"unit_time"`
@@ -2227,7 +2232,6 @@ type UpdateSubscribeRequest struct {
SpeedLimit int64 `json:"speed_limit"`
DeviceLimit int64 `json:"device_limit"`
Quota int64 `json:"quota"`
GroupId int64 `json:"group_id"`
Nodes []int64 `json:"nodes"`
NodeTags []string `json:"node_tags"`
Show *bool `json:"show"`