This commit is contained in:
unknown
2026-02-04 20:27:13 +08:00
commit 3b042d1dad
9410 changed files with 1488147 additions and 0 deletions

View File

@@ -0,0 +1,114 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package packages
import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
"github.com/TeaOSLab/EdgeUser/internal/configloaders"
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
)
type BuyAction struct {
actionutils.ParentAction
}
func (this *BuyAction) Init() {
this.Nav("", "", "buy")
}
func (this *BuyAction) RunGet(params struct{}) {
// 检查权限
config, err := configloaders.LoadCacheableUserPriceConfig()
if err != nil {
this.ErrorPage(err)
return
}
if config == nil || !config.IsOn || config.EnablePlans || !config.EnableTrafficPackages {
this.WriteString("管理员未开启相关配置")
return
}
// 价格
pricesResp, err := this.RPC().TrafficPackagePriceRPC().FindAllTrafficPackagePrices(this.UserContext(), &pb.FindAllTrafficPackagePricesRequest{})
if err != nil {
this.ErrorPage(err)
return
}
var priceMap = map[string]float64{} // packageId@regionId@periodId => price
var allPackageIdMap = map[int64]bool{}
var allRegionIdMap = map[int64]bool{}
var allPeriodIdMap = map[int64]bool{}
for _, price := range pricesResp.TrafficPackagePrices {
if price.Price > 0 {
allPackageIdMap[price.TrafficPackageId] = true
allRegionIdMap[price.NodeRegionId] = true
allPeriodIdMap[price.TrafficPackagePeriodId] = true
var key = types.String(price.TrafficPackageId) + "@" + types.String(price.NodeRegionId) + "@" + types.String(price.TrafficPackagePeriodId)
priceMap[key] = price.Price
}
}
this.Data["prices"] = priceMap
// 流量包
var packageMaps = []maps.Map{}
packagesResp, err := this.RPC().TrafficPackageRPC().FindAllAvailableTrafficPackages(this.UserContext(), &pb.FindAllAvailableTrafficPackagesRequest{})
if err != nil {
this.ErrorPage(err)
return
}
for _, p := range packagesResp.TrafficPackages {
_, hasPrice := allPackageIdMap[p.Id]
if hasPrice {
packageMaps = append(packageMaps, maps.Map{
"id": p.Id,
"size": p.Size,
"unit": p.Unit,
})
}
}
this.Data["packages"] = packageMaps
// 区域
var regionMaps = []maps.Map{}
regionsResp, err := this.RPC().NodeRegionRPC().FindAllAvailableNodeRegions(this.UserContext(), &pb.FindAllAvailableNodeRegionsRequest{})
if err != nil {
this.ErrorPage(err)
return
}
for _, region := range regionsResp.NodeRegions {
_, hasPrice := allRegionIdMap[region.Id]
if hasPrice {
regionMaps = append(regionMaps, maps.Map{
"id": region.Id,
"name": region.Name,
})
}
}
this.Data["regions"] = regionMaps
// 周期
var periodMaps = []maps.Map{}
periodResp, err := this.RPC().TrafficPackagePeriodRPC().FindAllAvailableTrafficPackagePeriods(this.UserContext(), &pb.FindAllAvailableTrafficPackagePeriodsRequest{})
if err != nil {
this.ErrorPage(err)
return
}
for _, period := range periodResp.TrafficPackagePeriods {
_, hasPrice := allPeriodIdMap[period.Id]
if hasPrice {
periodMaps = append(periodMaps, maps.Map{
"id": period.Id,
"count": period.Count,
"unit": period.Unit,
"unitName": userconfigs.TrafficPackagePeriodUnitName(period.Unit),
})
}
}
this.Data["periods"] = periodMaps
this.Show()
}

View File

@@ -0,0 +1,251 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package packages
import (
"encoding/json"
"errors"
"fmt"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
"github.com/TeaOSLab/EdgeUser/internal/configloaders"
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeUser/internal/web/actions/default/finance/financeutils"
"github.com/iwind/TeaGo/types"
"strings"
)
type ConfirmAction struct {
actionutils.ParentAction
}
func (this *ConfirmAction) Init() {
this.Nav("", "", "buy")
}
func (this *ConfirmAction) RunGet(params struct {
PackageId int64
RegionId int64
PeriodId int64
Count int32
}) {
// parameters
this.Data["packageId"] = params.PackageId
this.Data["regionId"] = params.RegionId
this.Data["periodId"] = params.PeriodId
// 检查权限
config, err := configloaders.LoadCacheableUserPriceConfig()
if err != nil {
this.ErrorPage(err)
return
}
if config == nil || !config.IsOn || config.EnablePlans || !config.EnableTrafficPackages {
this.WriteString("管理员未开启相关配置")
return
}
// package
packageResp, err := this.RPC().TrafficPackageRPC().FindTrafficPackage(this.UserContext(), &pb.FindTrafficPackageRequest{TrafficPackageId: params.PackageId})
if err != nil {
this.ErrorPage(err)
return
}
var p = packageResp.TrafficPackage
if p == nil || !p.IsOn {
this.NotFound("TrafficPackage", params.PackageId)
return
}
this.Data["packageName"] = types.String(p.Size) + strings.ToUpper(p.Unit)
// region
regionResp, err := this.RPC().NodeRegionRPC().FindEnabledNodeRegion(this.UserContext(), &pb.FindEnabledNodeRegionRequest{NodeRegionId: params.RegionId})
if err != nil {
this.ErrorPage(err)
return
}
var region = regionResp.NodeRegion
if region == nil || !region.IsOn {
this.NotFound("NodeRegion", params.RegionId)
return
}
this.Data["regionName"] = region.Name
// period
periodResp, err := this.RPC().TrafficPackagePeriodRPC().FindTrafficPackagePeriod(this.UserContext(), &pb.FindTrafficPackagePeriodRequest{TrafficPackagePeriodId: params.PeriodId})
if err != nil {
this.ErrorPage(err)
return
}
var period = periodResp.TrafficPackagePeriod
if period == nil || !period.IsOn {
this.NotFound("TrafficPackagePeriod", params.PeriodId)
return
}
this.Data["periodName"] = types.String(period.Count) + userconfigs.TrafficPackagePeriodUnitName(period.Unit)
// count
if params.Count <= 0 {
this.ErrorPage(errors.New("invalid 'count' parameter"))
return
}
this.Data["count"] = params.Count
// price
priceResp, err := this.RPC().TrafficPackagePriceRPC().FindTrafficPackagePrice(this.UserContext(), &pb.FindTrafficPackagePriceRequest{
TrafficPackageId: params.PackageId,
NodeRegionId: params.RegionId,
TrafficPackagePeriodId: params.PeriodId,
Count: params.Count,
})
if err != nil {
this.ErrorPage(err)
return
}
if priceResp.Price == 0 {
this.ErrorPage(errors.New("invalid parameters: could not retrieve price"))
return
}
this.Data["amount"] = priceResp.Amount
this.Show()
}
func (this *ConfirmAction) RunPost(params struct {
PackageId int64
RegionId int64
PeriodId int64
Count int32
MethodCode string
}) {
// 检查权限
config, err := configloaders.LoadCacheableUserPriceConfig()
if err != nil {
this.ErrorPage(err)
return
}
if config == nil || !config.IsOn || config.EnablePlans || !config.EnableTrafficPackages {
this.Fail("管理员未开启相关配置")
return
}
// 检查参数
if params.PackageId <= 0 {
this.Fail("请选择流量包规格")
return
}
if params.RegionId <= 0 {
this.Fail("请选择区域")
return
}
if params.PeriodId <= 0 {
this.Fail("请选择有效期")
return
}
if params.Count <= 0 {
this.Fail("请选择数量")
return
}
if params.Count > 20 {
this.Fail("一次性最多只能购买20个")
return
}
// period
periodResp, err := this.RPC().TrafficPackagePeriodRPC().FindTrafficPackagePeriod(this.UserContext(), &pb.FindTrafficPackagePeriodRequest{TrafficPackagePeriodId: params.PeriodId})
if err != nil {
this.ErrorPage(err)
return
}
var period = periodResp.TrafficPackagePeriod
if period == nil || !period.IsOn {
this.NotFound("TrafficPackagePeriod", params.PeriodId)
return
}
// 检查价格
priceResp, err := this.RPC().TrafficPackagePriceRPC().FindTrafficPackagePrice(this.UserContext(), &pb.FindTrafficPackagePriceRequest{
TrafficPackageId: params.PackageId,
NodeRegionId: params.RegionId,
TrafficPackagePeriodId: params.PeriodId,
Count: params.Count,
})
if err != nil {
this.ErrorPage(err)
return
}
if priceResp.Amount <= 0 {
this.Fail("当前流量包没有设定价格,无法购买")
return
}
var amount = priceResp.Amount
this.Data["packageId"] = params.PackageId
this.Data["regionId"] = params.RegionId
this.Data["periodId"] = params.PeriodId
this.Data["count"] = params.Count
// 使用余额购买
this.Data["success"] = false
this.Data["orderCode"] = ""
if params.MethodCode == "@balance" {
balance, err := financeutils.FindUserBalance(this.UserContext())
if err != nil {
this.ErrorPage(err)
return
}
if amount > balance {
this.Fail("当前余额不足,需要:" + fmt.Sprintf("%.2f元", amount) + ",现有:" + fmt.Sprintf("%.2f元", balance) + " ,请充值后再试")
return
}
// 直接购买
_, err = this.RPC().UserTrafficPackageRPC().BuyUserTrafficPackage(this.UserContext(), &pb.BuyUserTrafficPackageRequest{
UserId: this.UserId(),
TrafficPackageId: params.PackageId,
NodeRegionId: params.RegionId,
TrafficPackagePeriodId: params.PeriodId,
Count: params.Count,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["success"] = true
this.Success()
return
}
// 生成订单
var orderParams = &userconfigs.OrderTypeBuyTrafficPackageParams{
PackageId: params.PackageId,
RegionId: params.RegionId,
PeriodId: params.PeriodId,
PeriodCount: period.Count,
PeriodUnit: period.Unit,
Count: params.Count,
}
orderParamsJSON, err := json.Marshal(orderParams)
if err != nil {
this.ErrorPage(err)
return
}
resp, err := this.RPC().UserOrderRPC().CreateUserOrder(this.UserContext(), &pb.CreateUserOrderRequest{
Type: userconfigs.OrderTypeBuyTrafficPackage,
OrderMethodCode: params.MethodCode,
Amount: amount,
ParamsJSON: orderParamsJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["orderCode"] = resp.Code
this.Success()
}

View File

@@ -0,0 +1,104 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package packages
import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
"github.com/TeaOSLab/EdgeUser/internal/configloaders"
"github.com/TeaOSLab/EdgeUser/internal/utils/dateutils"
"github.com/TeaOSLab/EdgeUser/internal/utils/numberutils"
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "index")
}
func (this *IndexAction) RunGet(params struct {
Type string
}) {
this.Data["type"] = params.Type
// 检查权限
config, err := configloaders.LoadCacheableUserPriceConfig()
if err != nil {
this.ErrorPage(err)
return
}
if config == nil || !config.IsOn || config.EnablePlans || !config.EnableTrafficPackages {
this.WriteString("管理员未开启相关配置")
return
}
// 检查有效的流量包数量
countResp, err := this.RPC().UserTrafficPackageRPC().CountUserTrafficPackages(this.UserContext(), &pb.CountUserTrafficPackagesRequest{
UserId: this.UserId(),
AvailableOnly: params.Type == "",
})
if err != nil {
this.ErrorPage(err)
return
}
var count = countResp.Count
var page = this.NewPage(count)
this.Data["page"] = page.AsHTML()
// 列表
userPackagesResp, err := this.RPC().UserTrafficPackageRPC().ListUserTrafficPackages(this.UserContext(), &pb.ListUserTrafficPackagesRequest{
UserId: this.UserId(),
AvailableOnly: params.Type == "",
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)
return
}
var userPackageMaps = []maps.Map{}
for _, userPackage := range userPackagesResp.UserTrafficPackages {
// package
var packageMap maps.Map
if userPackage.TrafficPackage != nil {
packageMap = maps.Map{
"id": userPackage.TrafficPackage.Id,
"size": userPackage.TrafficPackage.Size,
"unit": userPackage.TrafficPackage.Unit,
}
}
// region
var regionMap maps.Map
if userPackage.NodeRegion != nil {
regionMap = maps.Map{
"id": userPackage.NodeRegion.Id,
"name": userPackage.NodeRegion.Name,
}
}
userPackageMaps = append(userPackageMaps, maps.Map{
"id": userPackage.Id,
"dayFrom": dateutils.SplitYmd(userPackage.DayFrom),
"dayTo": dateutils.SplitYmd(userPackage.DayTo),
"package": packageMap,
"region": regionMap,
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", userPackage.CreatedAt),
"periodCount": userPackage.TrafficPackagePeriodCount,
"periodUnitName": userconfigs.TrafficPackagePeriodUnitName(userPackage.TrafficPackagePeriodUnit),
"usedSize": numberutils.FormatBytes(userPackage.UsedBytes),
"availableSize": numberutils.FormatBytes(userPackage.TotalBytes - userPackage.UsedBytes),
"createTime": timeutil.FormatTime("Y-m-d H:i:s", userPackage.CreatedAt),
"isExpired": userPackage.DayTo < timeutil.Format("Ymd"),
"isUsedAll": userPackage.UsedBytes >= userPackage.TotalBytes,
})
}
this.Data["userPackages"] = userPackageMaps
this.Show()
}

View File

@@ -0,0 +1,23 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package packages
import (
"github.com/TeaOSLab/EdgeUser/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth("")).
Data("teaMenu", "servers").
Data("teaSubMenu", "trafficPackage").
Prefix("/servers/packages").
Get("", new(IndexAction)).
Get("/buy", new(BuyAction)).
GetPost("/confirm", new(ConfirmAction)).
Post("/price", new(PriceAction)).
EndAll()
})
}

View File

@@ -0,0 +1,41 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
package packages
import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeUser/internal/web/actions/actionutils"
)
type PriceAction struct {
actionutils.ParentAction
}
func (this *PriceAction) RunPost(params struct {
PackageId int64
RegionId int64
PeriodId int64
Count int32
}) {
if params.PackageId <= 0 || params.RegionId <= 0 || params.PeriodId <= 0 || params.Count <= 0 {
this.Data["price"] = 0
this.Data["amount"] = 0
this.Success()
return
}
resp, err := this.RPC().TrafficPackagePriceRPC().FindTrafficPackagePrice(this.UserContext(), &pb.FindTrafficPackagePriceRequest{
TrafficPackageId: params.PackageId,
NodeRegionId: params.RegionId,
TrafficPackagePeriodId: params.PeriodId,
Count: params.Count,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["price"] = resp.Price
this.Data["amount"] = resp.Amount
this.Success()
}