1.4.5.2
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package accountutils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
// InitAccount 初始化账户
|
||||
func InitAccount(parent *actionutils.ParentAction, accountId int64) (*pb.UserAccount, error) {
|
||||
resp, err := parent.RPC().UserAccountRPC().FindEnabledUserAccount(parent.AdminContext(), &pb.FindEnabledUserAccountRequest{UserAccountId: accountId})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var account = resp.UserAccount
|
||||
if account == nil {
|
||||
return nil, errors.New("can not find account with id '" + types.String(accountId) + "'")
|
||||
}
|
||||
|
||||
var userMap = maps.Map{"fullname": "", "username": ""}
|
||||
var user = account.User
|
||||
if user != nil {
|
||||
userMap = maps.Map{"fullname": user.Fullname, "username": user.Username}
|
||||
}
|
||||
|
||||
parent.Data["account"] = maps.Map{
|
||||
"id": account.Id,
|
||||
"user": userMap,
|
||||
}
|
||||
|
||||
return account, nil
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package account
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/accounts/account/accountutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"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 {
|
||||
AccountId int64
|
||||
Keyword string
|
||||
}) {
|
||||
this.Data["keyword"] = ""
|
||||
|
||||
account, err := accountutils.InitAccount(this.Parent(), params.AccountId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var accountMap = this.Data.GetMap("account")
|
||||
accountMap["total"] = account.Total
|
||||
accountMap["totalFrozen"] = account.TotalFrozen
|
||||
this.Data["account"] = accountMap
|
||||
|
||||
// 最近操作记录
|
||||
logsResp, err := this.RPC().UserAccountLogRPC().ListUserAccountLogs(this.AdminContext(), &pb.ListUserAccountLogsRequest{
|
||||
UserAccountId: account.Id,
|
||||
Offset: 0,
|
||||
Size: 10,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var logMaps = []maps.Map{}
|
||||
for _, log := range logsResp.UserAccountLogs {
|
||||
logMaps = append(logMaps, maps.Map{
|
||||
"id": log.Id,
|
||||
"description": log.Description,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", log.CreatedAt),
|
||||
"delta": log.Delta,
|
||||
"deltaFrozen": log.DeltaFrozen,
|
||||
"total": log.Total,
|
||||
"totalFrozen": log.TotalFrozen,
|
||||
"event": userconfigs.FindAccountEvent(log.EventType),
|
||||
})
|
||||
}
|
||||
this.Data["logs"] = logMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package account
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/accounts/account/accountutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type LogsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *LogsAction) Init() {
|
||||
this.Nav("", "", "log")
|
||||
}
|
||||
|
||||
func (this *LogsAction) RunGet(params struct {
|
||||
AccountId int64
|
||||
Keyword string
|
||||
}) {
|
||||
this.Data["keyword"] = params.Keyword
|
||||
|
||||
_, err := accountutils.InitAccount(this.Parent(), params.AccountId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
countResp, err := this.RPC().UserAccountLogRPC().CountUserAccountLogs(this.AdminContext(), &pb.CountUserAccountLogsRequest{UserAccountId: params.AccountId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var count = countResp.Count
|
||||
var page = this.NewPage(count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
logsResp, err := this.RPC().UserAccountLogRPC().ListUserAccountLogs(this.AdminContext(), &pb.ListUserAccountLogsRequest{
|
||||
UserAccountId: params.AccountId,
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var logMaps = []maps.Map{}
|
||||
for _, log := range logsResp.UserAccountLogs {
|
||||
logMaps = append(logMaps, maps.Map{
|
||||
"id": log.Id,
|
||||
"description": log.Description,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", log.CreatedAt),
|
||||
"delta": log.Delta,
|
||||
"deltaFrozen": log.DeltaFrozen,
|
||||
"total": log.Total,
|
||||
"totalFrozen": log.TotalFrozen,
|
||||
"event": userconfigs.FindAccountEvent(log.EventType),
|
||||
})
|
||||
}
|
||||
this.Data["logs"] = logMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package account
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/accounts/account/accountutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type UpdateAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateAction) Init() {
|
||||
this.Nav("", "", "update")
|
||||
}
|
||||
|
||||
func (this *UpdateAction) RunGet(params struct {
|
||||
AccountId int64
|
||||
}) {
|
||||
account, err := accountutils.InitAccount(this.Parent(), params.AccountId)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var accountMap = this.Data.GetMap("account")
|
||||
accountMap["total"] = account.Total
|
||||
accountMap["totalFrozen"] = account.TotalFrozen
|
||||
this.Data["account"] = accountMap
|
||||
|
||||
this.Data["eventTypes"] = userconfigs.FindAllAccountEventTypes()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateAction) RunPost(params struct {
|
||||
AccountId int64
|
||||
EventType string
|
||||
Delta float64
|
||||
Description string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.UserAccount_LogUpdateUserAccount, params.AccountId, params.Description)
|
||||
|
||||
if params.AccountId <= 0 {
|
||||
this.Fail("请选择要操作的账户")
|
||||
}
|
||||
|
||||
var event = userconfigs.FindAccountEvent(params.EventType)
|
||||
if event == nil {
|
||||
this.Fail("请选择操作类型")
|
||||
}
|
||||
|
||||
if params.Delta < 0 {
|
||||
this.Fail("操作金额不能小于0")
|
||||
}
|
||||
|
||||
var delta = params.Delta
|
||||
if !event.IsPositive {
|
||||
delta = -delta
|
||||
}
|
||||
accountResp, err := this.RPC().UserAccountRPC().FindEnabledUserAccount(this.AdminContext(), &pb.FindEnabledUserAccountRequest{UserAccountId: params.AccountId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var account = accountResp.UserAccount
|
||||
if account == nil {
|
||||
this.Fail("找不到用户的账户")
|
||||
}
|
||||
|
||||
// 检查余额是否足够
|
||||
if !event.IsPositive && delta+account.Total < 0 {
|
||||
this.Fail("账户余额不足,最多只能操作" + types.String(account.Total) + "元")
|
||||
}
|
||||
|
||||
_, err = this.RPC().UserAccountRPC().UpdateUserAccount(this.AdminContext(), &pb.UpdateUserAccountRequest{
|
||||
UserAccountId: account.Id,
|
||||
Delta: delta,
|
||||
EventType: params.EventType,
|
||||
Description: params.Description,
|
||||
ParamsJSON: nil,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
Keyword string
|
||||
}) {
|
||||
this.Data["keyword"] = params.Keyword
|
||||
|
||||
countResp, err := this.RPC().UserAccountRPC().CountUserAccounts(this.AdminContext(), &pb.CountUserAccountsRequest{Keyword: params.Keyword})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var count = countResp.Count
|
||||
var page = this.NewPage(count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
accountsResp, err := this.RPC().UserAccountRPC().ListUserAccounts(this.AdminContext(), &pb.ListUserAccountsRequest{
|
||||
Keyword: params.Keyword,
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var accountMaps = []maps.Map{}
|
||||
for _, account := range accountsResp.UserAccounts {
|
||||
if account.User == nil {
|
||||
account.User = &pb.User{}
|
||||
}
|
||||
|
||||
accountMaps = append(accountMaps, maps.Map{
|
||||
"id": account.Id,
|
||||
"total": account.Total,
|
||||
"user": maps.Map{
|
||||
"id": account.UserId,
|
||||
"username": account.User.Username,
|
||||
"fullname": account.User.Fullname,
|
||||
},
|
||||
})
|
||||
}
|
||||
this.Data["accounts"] = accountMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
//go:build plus
|
||||
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/accounts/account"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeFinance)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeFinance)).
|
||||
Data("teaMenu", "finance").
|
||||
Data("teaSubMenu", "accounts").
|
||||
|
||||
// 财务管理
|
||||
Prefix("/finance/accounts").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/update", new(UpdateAction)).
|
||||
Post("/userAccount", new(UserAccountAction)).
|
||||
|
||||
// 账户
|
||||
Prefix("/finance/accounts/account").
|
||||
Get("", new(account.IndexAction)).
|
||||
Get("/logs", new(account.LogsAction)).
|
||||
GetPost("/update", new(account.UpdateAction)).
|
||||
|
||||
//
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type UpdateAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateAction) Init() {
|
||||
this.Nav("", "", "update")
|
||||
}
|
||||
|
||||
func (this *UpdateAction) RunGet(params struct{}) {
|
||||
this.Data["eventTypes"] = userconfigs.FindAllAccountEventTypes()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateAction) RunPost(params struct {
|
||||
UserId int64
|
||||
EventType string
|
||||
Delta float64
|
||||
Description string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.UserAccount_LogUpdateUserAccount, params.UserId, params.Description)
|
||||
|
||||
if params.UserId <= 0 {
|
||||
this.Fail("请选择要操作的用户")
|
||||
}
|
||||
|
||||
var event = userconfigs.FindAccountEvent(params.EventType)
|
||||
if event == nil {
|
||||
this.Fail("请选择操作类型")
|
||||
}
|
||||
|
||||
if params.Delta < 0 {
|
||||
this.Fail("操作金额不能小于0")
|
||||
}
|
||||
|
||||
var delta = params.Delta
|
||||
if !event.IsPositive {
|
||||
delta = -delta
|
||||
}
|
||||
accountResp, err := this.RPC().UserAccountRPC().FindEnabledUserAccountWithUserId(this.AdminContext(), &pb.FindEnabledUserAccountWithUserIdRequest{UserId: params.UserId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var account = accountResp.UserAccount
|
||||
if account == nil {
|
||||
this.Fail("找不到用户的账户")
|
||||
}
|
||||
|
||||
// 检查余额是否足够
|
||||
if !event.IsPositive && delta+account.Total < 0 {
|
||||
this.Fail("账户余额不足,最多只能操作" + types.String(account.Total) + "元")
|
||||
}
|
||||
|
||||
_, err = this.RPC().UserAccountRPC().UpdateUserAccount(this.AdminContext(), &pb.UpdateUserAccountRequest{
|
||||
UserAccountId: account.Id,
|
||||
Delta: delta,
|
||||
EventType: params.EventType,
|
||||
Description: params.Description,
|
||||
ParamsJSON: nil,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UserAccountAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UserAccountAction) RunPost(params struct {
|
||||
UserId int64
|
||||
}) {
|
||||
resp, err := this.RPC().UserAccountRPC().FindEnabledUserAccountWithUserId(this.AdminContext(), &pb.FindEnabledUserAccountWithUserIdRequest{UserId: params.UserId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var account = resp.UserAccount
|
||||
if account == nil {
|
||||
account = &pb.UserAccount{}
|
||||
}
|
||||
this.Data["account"] = maps.Map{
|
||||
"total": account.Total,
|
||||
"totalFrozen": account.TotalFrozen,
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
173
EdgeAdmin/internal/web/actions/default/finance/bills/bill.go
Normal file
173
EdgeAdmin/internal/web/actions/default/finance/bills/bill.go
Normal file
@@ -0,0 +1,173 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package bills
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type BillAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *BillAction) Init() {
|
||||
this.Nav("", "", "index")
|
||||
}
|
||||
|
||||
func (this *BillAction) RunGet(params struct {
|
||||
BillId int64
|
||||
}) {
|
||||
userBillResp, err := this.RPC().UserBillRPC().FindUserBill(this.AdminContext(), &pb.FindUserBillRequest{UserBillId: params.BillId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var bill = userBillResp.UserBill
|
||||
if bill == nil {
|
||||
this.NotFound("user bill", params.BillId)
|
||||
return
|
||||
}
|
||||
|
||||
var userMap maps.Map = nil
|
||||
if bill.User != nil {
|
||||
userMap = maps.Map{
|
||||
"id": bill.User.Id,
|
||||
"fullname": bill.User.Fullname,
|
||||
"username": bill.User.Username,
|
||||
}
|
||||
}
|
||||
|
||||
var month = bill.Month
|
||||
var dayFrom = bill.DayFrom
|
||||
var dayTo = bill.DayTo
|
||||
|
||||
if len(month) == 6 {
|
||||
month = month[:4] + "-" + month[4:]
|
||||
}
|
||||
if len(dayFrom) == 8 {
|
||||
dayFrom = dayFrom[:4] + "-" + dayFrom[4:6] + "-" + dayFrom[6:]
|
||||
}
|
||||
if len(dayTo) == 8 {
|
||||
dayTo = dayTo[:4] + "-" + dayTo[4:6] + "-" + dayTo[6:]
|
||||
}
|
||||
|
||||
this.Data["bill"] = maps.Map{
|
||||
"id": bill.Id,
|
||||
"isPaid": bill.IsPaid,
|
||||
"month": month,
|
||||
"dayFrom": dayFrom,
|
||||
"dayTo": dayTo,
|
||||
"amount": numberutils.FormatFloat(bill.Amount, 2),
|
||||
"typeName": bill.TypeName,
|
||||
"user": userMap,
|
||||
"description": bill.Description,
|
||||
"code": bill.Code,
|
||||
"canPay": bill.CanPay,
|
||||
"pricePeriodName": userconfigs.PricePeriodName(bill.PricePeriod),
|
||||
"pricePeriod": bill.PricePeriod,
|
||||
}
|
||||
|
||||
// 子账单
|
||||
var serverBillMaps = []maps.Map{}
|
||||
if (bill.Type == "traffic" || bill.Type == "trafficAndBandwidth") && bill.User != nil {
|
||||
countResp, err := this.RPC().ServerBillRPC().CountAllServerBills(this.AdminContext(), &pb.CountAllServerBillsRequest{
|
||||
UserId: bill.User.Id,
|
||||
Month: bill.Month,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var count = countResp.Count
|
||||
var page = this.NewPage(count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
serverBillsResp, err := this.RPC().ServerBillRPC().ListServerBills(this.AdminContext(), &pb.ListServerBillsRequest{
|
||||
UserId: bill.User.Id,
|
||||
Month: bill.Month,
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
for _, serverBill := range serverBillsResp.ServerBills {
|
||||
// server
|
||||
var serverMap = maps.Map{"id": 0}
|
||||
if serverBill.Server != nil {
|
||||
serverMap = maps.Map{
|
||||
"id": serverBill.Server.Id,
|
||||
"name": serverBill.Server.Name,
|
||||
}
|
||||
}
|
||||
|
||||
// plan
|
||||
var planMap = maps.Map{"id": 0}
|
||||
if serverBill.Plan != nil {
|
||||
planMap = maps.Map{
|
||||
"id": serverBill.Plan.Id,
|
||||
"name": serverBill.Plan.Name,
|
||||
"priceType": serverBill.Plan.PriceType,
|
||||
}
|
||||
}
|
||||
|
||||
serverBillMaps = append(serverBillMaps, maps.Map{
|
||||
"id": serverBill.Id,
|
||||
"server": serverMap,
|
||||
"plan": planMap,
|
||||
"traffic": numberutils.FormatBytes(serverBill.TotalTrafficBytes),
|
||||
"bandwidthPercentile": serverBill.BandwidthPercentile,
|
||||
"bandwidthPercentileSize": numberutils.FormatBytes(serverBill.BandwidthPercentileBytes),
|
||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", serverBill.CreatedAt),
|
||||
"amount": numberutils.FormatFloat(serverBill.Amount, 2),
|
||||
"priceType": serverBill.PriceType,
|
||||
})
|
||||
}
|
||||
}
|
||||
this.Data["serverBills"] = serverBillMaps
|
||||
|
||||
// traffic bills
|
||||
var trafficBillMaps = []maps.Map{}
|
||||
trafficBillsResp, err := this.RPC().UserTrafficBillRPC().FindUserTrafficBills(this.AdminContext(), &pb.FindUserTrafficBillsRequest{UserBillId: bill.Id})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
for _, trafficBill := range trafficBillsResp.UserTrafficBills {
|
||||
var regionMap = maps.Map{"id": 0}
|
||||
var nodeRegion = trafficBill.NodeRegion
|
||||
if nodeRegion != nil {
|
||||
regionMap = maps.Map{
|
||||
"id": nodeRegion.Id,
|
||||
"name": nodeRegion.Name,
|
||||
}
|
||||
} else if trafficBill.NodeRegionId > 0 {
|
||||
regionMap = maps.Map{
|
||||
"id": trafficBill.NodeRegionId,
|
||||
"name": "[" + this.Lang(codes.AdminCommon_Canceled) + "]",
|
||||
}
|
||||
}
|
||||
|
||||
trafficBillMaps = append(trafficBillMaps, maps.Map{
|
||||
"priceType": trafficBill.PriceType,
|
||||
"priceTypeName": userconfigs.PriceTypeName(trafficBill.PriceType),
|
||||
"trafficGB": numberutils.FormatBytes(int64(trafficBill.TrafficGB * (1 << 30))),
|
||||
"trafficPackageGB": numberutils.FormatBytes(int64(trafficBill.TrafficPackageGB * (1 << 30))),
|
||||
"bandwidthMB": numberutils.FormatBits(int64(trafficBill.BandwidthMB * (1 << 20))),
|
||||
"bandwidthPercentile": trafficBill.BandwidthPercentile,
|
||||
"amount": numberutils.FormatFloat(trafficBill.Amount, 2),
|
||||
"pricePerUnit": trafficBill.PricePerUnit,
|
||||
"region": regionMap,
|
||||
})
|
||||
}
|
||||
this.Data["trafficBills"] = trafficBillMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package bills
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
type GenerateAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *GenerateAction) Init() {
|
||||
this.Nav("", "", "generate")
|
||||
}
|
||||
|
||||
func (this *GenerateAction) RunGet(params struct{}) {
|
||||
this.Data["month"] = timeutil.Format("Ym", time.Now().AddDate(0, -1, 0))
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *GenerateAction) RunPost(params struct {
|
||||
Month string
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.Finance_LogBillGenerateManually, params.Month)
|
||||
|
||||
_, err := this.RPC().UserBillRPC().GenerateAllUserBills(this.AdminContext(), &pb.GenerateAllUserBillsRequest{Month: params.Month})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package bills
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
PaidFlag int32 `default:"-1"`
|
||||
UserId int64
|
||||
Month string
|
||||
}) {
|
||||
countResp, err := this.RPC().UserBillRPC().CountAllUserBills(this.AdminContext(), &pb.CountAllUserBillsRequest{
|
||||
PaidFlag: params.PaidFlag,
|
||||
UserId: params.UserId,
|
||||
Month: params.Month,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var page = this.NewPage(countResp.Count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
billsResp, err := this.RPC().UserBillRPC().ListUserBills(this.AdminContext(), &pb.ListUserBillsRequest{
|
||||
PaidFlag: params.PaidFlag,
|
||||
UserId: params.UserId,
|
||||
Month: params.Month,
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var billMaps = []maps.Map{}
|
||||
for _, bill := range billsResp.UserBills {
|
||||
var userMap maps.Map = nil
|
||||
if bill.User != nil {
|
||||
userMap = maps.Map{
|
||||
"id": bill.User.Id,
|
||||
"fullname": bill.User.Fullname,
|
||||
"username": bill.User.Username,
|
||||
}
|
||||
}
|
||||
|
||||
var month = bill.Month
|
||||
var dayFrom = bill.DayFrom
|
||||
var dayTo = bill.DayTo
|
||||
|
||||
if len(month) == 6 {
|
||||
month = month[:4] + "-" + month[4:]
|
||||
}
|
||||
if len(dayFrom) == 8 {
|
||||
dayFrom = dayFrom[:4] + "-" + dayFrom[4:6] + "-" + dayFrom[6:]
|
||||
}
|
||||
if len(dayTo) == 8 {
|
||||
dayTo = dayTo[:4] + "-" + dayTo[4:6] + "-" + dayTo[6:]
|
||||
}
|
||||
|
||||
billMaps = append(billMaps, maps.Map{
|
||||
"id": bill.Id,
|
||||
"isPaid": bill.IsPaid,
|
||||
"month": month,
|
||||
"dayFrom": dayFrom,
|
||||
"dayTo": dayTo,
|
||||
"amount": numberutils.FormatFloat(bill.Amount, 2),
|
||||
"typeName": bill.TypeName,
|
||||
"user": userMap,
|
||||
"description": bill.Description,
|
||||
"code": bill.Code,
|
||||
"canPay": bill.CanPay,
|
||||
"pricePeriodName": userconfigs.PricePeriodName(bill.PricePeriod),
|
||||
"pricePeriod": bill.PricePeriod,
|
||||
"isOverdue": bill.IsOverdue,
|
||||
})
|
||||
}
|
||||
this.Data["bills"] = billMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
28
EdgeAdmin/internal/web/actions/default/finance/bills/init.go
Normal file
28
EdgeAdmin/internal/web/actions/default/finance/bills/init.go
Normal file
@@ -0,0 +1,28 @@
|
||||
//go:build plus
|
||||
|
||||
package bills
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeFinance)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeFinance)).
|
||||
Data("teaMenu", "finance").
|
||||
Data("teaSubMenu", "bills").
|
||||
|
||||
// 财务管理
|
||||
Prefix("/finance/bills").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/generate", new(GenerateAction)).
|
||||
Post("/pay", new(PayAction)).
|
||||
Get("/bill", new(BillAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
58
EdgeAdmin/internal/web/actions/default/finance/bills/pay.go
Normal file
58
EdgeAdmin/internal/web/actions/default/finance/bills/pay.go
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package bills
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type PayAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *PayAction) RunPost(params struct {
|
||||
BillId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.UserBill_LogPayUserBill, params.BillId)
|
||||
|
||||
billResp, err := this.RPC().UserBillRPC().FindUserBill(this.AdminContext(), &pb.FindUserBillRequest{UserBillId: params.BillId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var bill = billResp.UserBill
|
||||
if bill == nil {
|
||||
this.Fail("找不到要支付的账单")
|
||||
}
|
||||
|
||||
if bill.IsPaid {
|
||||
this.Fail("此账单已支付,不需要重复支付")
|
||||
}
|
||||
|
||||
// 账号余额
|
||||
accountResp, err := this.RPC().UserAccountRPC().FindEnabledUserAccountWithUserId(this.AdminContext(), &pb.FindEnabledUserAccountWithUserIdRequest{UserId: bill.User.Id})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var account = accountResp.UserAccount
|
||||
if account == nil {
|
||||
this.Fail("当前用户还没有账号")
|
||||
}
|
||||
|
||||
if account.Total < bill.Amount {
|
||||
this.Fail("账号余额不足,当前余额:" + types.String(account.Total) + ",需要支付:" + types.String(bill.Amount))
|
||||
}
|
||||
|
||||
// 支付
|
||||
_, err = this.RPC().UserBillRPC().PayUserBill(this.AdminContext(), &pb.PayUserBillRequest{UserBillId: params.BillId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
//go:build plus
|
||||
|
||||
package fee
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/financeutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type BandwidthAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *BandwidthAction) Init() {
|
||||
this.Nav("", "", "bandwidth")
|
||||
}
|
||||
|
||||
func (this *BandwidthAction) RunGet(params struct{}) {
|
||||
// 财务相关配置
|
||||
config, err := financeutils.ReadPriceConfig(this.AdminContext())
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["config"] = config
|
||||
|
||||
// 所有价格项目
|
||||
itemsResp, err := this.RPC().NodePriceItemRPC().FindAllAvailableNodePriceItems(this.AdminContext(), &pb.FindAllAvailableNodePriceItemsRequest{Type: userconfigs.PriceTypeBandwidth})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var itemMaps = []maps.Map{}
|
||||
for _, item := range itemsResp.NodePriceItems {
|
||||
var maxSize string
|
||||
if item.BitsTo == 0 {
|
||||
maxSize = "∞"
|
||||
} else {
|
||||
maxSize = numberutils.FormatBits(item.BitsTo)
|
||||
}
|
||||
|
||||
itemMaps = append(itemMaps, maps.Map{
|
||||
"id": item.Id,
|
||||
"name": item.Name,
|
||||
"minSize": numberutils.FormatBits(item.BitsFrom),
|
||||
"maxSize": maxSize,
|
||||
})
|
||||
}
|
||||
this.Data["items"] = itemMaps
|
||||
|
||||
// 所有区域
|
||||
regionsResp, err := this.RPC().NodeRegionRPC().FindAllAvailableNodeRegions(this.AdminContext(), &pb.FindAllAvailableNodeRegionsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var regionMaps = []maps.Map{}
|
||||
for _, region := range regionsResp.NodeRegions {
|
||||
pricesMap := map[string]float32{}
|
||||
if len(region.PricesJSON) > 0 {
|
||||
err = json.Unmarshal(region.PricesJSON, &pricesMap)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
regionMaps = append(regionMaps, maps.Map{
|
||||
"id": region.Id,
|
||||
"isOn": region.IsOn,
|
||||
"name": region.Name,
|
||||
"prices": pricesMap,
|
||||
})
|
||||
}
|
||||
this.Data["regions"] = regionMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
104
EdgeAdmin/internal/web/actions/default/finance/fee/calculator.go
Normal file
104
EdgeAdmin/internal/web/actions/default/finance/fee/calculator.go
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package fee
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/financeutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type CalculatorAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CalculatorAction) Init() {
|
||||
this.Nav("", "", "calculator")
|
||||
}
|
||||
|
||||
func (this *CalculatorAction) RunGet(params struct{}) {
|
||||
// 财务相关配置
|
||||
config, err := financeutils.ReadPriceConfig(this.AdminContext())
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["config"] = config
|
||||
|
||||
// 所有区域
|
||||
regionsResp, err := this.RPC().NodeRegionRPC().FindAllAvailableNodeRegions(this.AdminContext(), &pb.FindAllAvailableNodeRegionsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var regionMaps = []maps.Map{}
|
||||
for _, region := range regionsResp.NodeRegions {
|
||||
regionMaps = append(regionMaps, maps.Map{
|
||||
"id": region.Id,
|
||||
"name": region.Name,
|
||||
})
|
||||
}
|
||||
this.Data["regions"] = regionMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CalculatorAction) RunPost(params struct {
|
||||
PriceType string
|
||||
|
||||
Traffic float64
|
||||
TrafficUnit string
|
||||
|
||||
Bandwidth float64
|
||||
BandwidthUnit string
|
||||
|
||||
RegionId int64
|
||||
|
||||
Must *actions.Must
|
||||
}) {
|
||||
var trafficGB float64 = 0
|
||||
var bandwidthMB float64 = 0
|
||||
|
||||
switch params.PriceType {
|
||||
case userconfigs.PriceTypeTraffic:
|
||||
switch params.TrafficUnit {
|
||||
case "gb":
|
||||
trafficGB = params.Traffic
|
||||
case "tb":
|
||||
trafficGB = params.Traffic * (1 << 10)
|
||||
case "eb":
|
||||
trafficGB = params.Traffic * (1 << 20)
|
||||
}
|
||||
case userconfigs.PriceTypeBandwidth:
|
||||
switch params.BandwidthUnit {
|
||||
case "mb":
|
||||
bandwidthMB = params.Bandwidth
|
||||
case "gb":
|
||||
bandwidthMB = params.Bandwidth * (1 << 10)
|
||||
case "tb":
|
||||
bandwidthMB = params.Bandwidth * (1 << 20)
|
||||
}
|
||||
default:
|
||||
this.Fail("请选择正确的计费类型")
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := this.RPC().PriceRPC().CalculatePrice(this.AdminContext(), &pb.CalculatePriceRequest{
|
||||
PriceType: params.PriceType,
|
||||
TrafficGB: trafficGB,
|
||||
BandwidthMB: bandwidthMB,
|
||||
NodeRegionId: params.RegionId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["amount"] = resp.Amount
|
||||
this.Data["amountFormatted"] = numberutils.FormatFloat(resp.Amount, 2)
|
||||
this.Data["hasRegionPrice"] = resp.HasNodeRegionPrice
|
||||
this.Success()
|
||||
}
|
||||
188
EdgeAdmin/internal/web/actions/default/finance/fee/index.go
Normal file
188
EdgeAdmin/internal/web/actions/default/finance/fee/index.go
Normal file
@@ -0,0 +1,188 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package fee
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/financeutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "basic")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
config, err := financeutils.ReadPriceConfig(this.AdminContext())
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["config"] = config
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunPost(params struct {
|
||||
IsOn bool
|
||||
PriceType string
|
||||
PricePeriod string
|
||||
TrafficPriceJSON []byte
|
||||
BandwidthPriceJSON []byte
|
||||
UserCanChangePriceType bool
|
||||
UserCanChangePricePeriod bool
|
||||
EnablePlans bool
|
||||
ShowPlansInUserSystem bool
|
||||
EnableTrafficPackages bool
|
||||
ShowTrafficPackages bool
|
||||
UserUIShowPrices bool
|
||||
|
||||
UnpaidBillPolicyIsOn bool
|
||||
UnpaidBillPolicyMinDailyBillDays int32
|
||||
UnpaidBillPolicyMinMonthlyBillDays int32
|
||||
UnpaidBillPolicyDisableServers bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.FinanceFee_LogUpdateFeeSetting)
|
||||
|
||||
valueResp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeUserPriceConfig})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var valueJSON = valueResp.ValueJSON
|
||||
var priceConfig = userconfigs.DefaultUserPriceConfig()
|
||||
if len(valueJSON) > 0 {
|
||||
err = json.Unmarshal(valueJSON, priceConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
priceConfig.IsOn = params.IsOn
|
||||
|
||||
if !userconfigs.IsValidPricePeriod(params.PricePeriod) {
|
||||
this.Fail("错误的结算周期 '" + params.PricePeriod + "'")
|
||||
return
|
||||
}
|
||||
priceConfig.DefaultPricePeriod = params.PricePeriod
|
||||
priceConfig.UserCanChangePriceType = params.UserCanChangePriceType
|
||||
priceConfig.UserCanChangePricePeriod = params.UserCanChangePricePeriod
|
||||
|
||||
priceConfig.EnablePlans = params.EnablePlans
|
||||
priceConfig.ShowPlansInUserSystem = params.ShowPlansInUserSystem
|
||||
|
||||
priceConfig.EnableTrafficPackages = params.EnableTrafficPackages
|
||||
priceConfig.ShowTrafficPackages = params.ShowTrafficPackages
|
||||
priceConfig.UserUI.ShowPrices = params.UserUIShowPrices
|
||||
|
||||
priceConfig.DefaultPriceType = params.PriceType
|
||||
|
||||
switch params.PriceType {
|
||||
case serverconfigs.PlanPriceTypeTraffic:
|
||||
if len(params.TrafficPriceJSON) == 0 {
|
||||
this.Fail("请设置流量价格")
|
||||
}
|
||||
case serverconfigs.PlanPriceTypeBandwidth:
|
||||
if len(params.BandwidthPriceJSON) == 0 {
|
||||
this.Fail("请设置带宽价格")
|
||||
}
|
||||
default:
|
||||
this.Fail("请选择默认计费方式")
|
||||
return
|
||||
}
|
||||
|
||||
// 流量价格
|
||||
if len(params.TrafficPriceJSON) > 0 {
|
||||
var config = &serverconfigs.PlanTrafficPriceConfig{}
|
||||
err := json.Unmarshal(params.TrafficPriceJSON, config)
|
||||
if err != nil {
|
||||
this.Fail("流量价格设置错误:" + err.Error())
|
||||
}
|
||||
|
||||
if params.PriceType == serverconfigs.PlanPriceTypeTraffic || params.UserCanChangePriceType {
|
||||
if config.Base <= 0 && len(config.Ranges) == 0 {
|
||||
this.Fail("流量基础价格和流量阶梯价格必须至少填写一个")
|
||||
}
|
||||
}
|
||||
priceConfig.DefaultTrafficPriceConfig = config
|
||||
}
|
||||
|
||||
// 带宽价格
|
||||
if len(params.BandwidthPriceJSON) > 0 {
|
||||
var config = &serverconfigs.PlanBandwidthPriceConfig{}
|
||||
err := json.Unmarshal(params.BandwidthPriceJSON, config)
|
||||
if err != nil {
|
||||
this.Fail("带宽价格设置错误:" + err.Error())
|
||||
}
|
||||
|
||||
if params.PriceType == serverconfigs.PlanPriceTypeBandwidth || params.UserCanChangePriceType {
|
||||
if config.Percentile <= 0 {
|
||||
this.Fail("带宽百分位必须大于0")
|
||||
}
|
||||
if config.Percentile > 100 {
|
||||
this.Fail("带宽百分位必须不大于100")
|
||||
}
|
||||
if config.Base <= 0 && len(config.Ranges) == 0 {
|
||||
this.Fail("带宽基础价格和带宽阶梯价格必须至少填写一个")
|
||||
}
|
||||
}
|
||||
priceConfig.DefaultBandwidthPriceConfig = config
|
||||
|
||||
// 同步修改UserUI中的用量统计设置
|
||||
uiConfig, err := configloaders.LoadUserUIConfig()
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if uiConfig != nil && uiConfig.TrafficStats.BandwidthAlgo != config.BandwidthAlgo {
|
||||
uiConfig.TrafficStats.BandwidthAlgo = config.BandwidthAlgo
|
||||
err = configloaders.UpdateUserUIConfig(uiConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 未支付账单策略
|
||||
priceConfig.UnpaidBillPolicy.IsOn = params.UnpaidBillPolicyIsOn
|
||||
priceConfig.UnpaidBillPolicy.MinDailyBillDays = params.UnpaidBillPolicyMinDailyBillDays
|
||||
priceConfig.UnpaidBillPolicy.MinMonthlyBillDays = params.UnpaidBillPolicyMinMonthlyBillDays
|
||||
priceConfig.UnpaidBillPolicy.DisableServers = params.UnpaidBillPolicyDisableServers
|
||||
|
||||
financeConfigJSON, err := json.Marshal(priceConfig)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().SysSettingRPC().UpdateSysSetting(this.AdminContext(), &pb.UpdateSysSettingRequest{
|
||||
Code: systemconfigs.SettingCodeUserPriceConfig,
|
||||
ValueJSON: financeConfigJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 重置配置
|
||||
configloaders.ResetUserPriceConfig(priceConfig)
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
//go:build plus
|
||||
|
||||
package items
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type CreateBandwidthPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreateBandwidthPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreateBandwidthPopupAction) RunGet(params struct {
|
||||
}) {
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreateBandwidthPopupAction) RunPost(params struct {
|
||||
Name string
|
||||
MinMB uint32
|
||||
MaxMB uint32
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入名称")
|
||||
|
||||
if params.MinMB > params.MaxMB {
|
||||
params.MinMB, params.MaxMB = params.MaxMB, params.MinMB
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().NodePriceItemRPC().CreateNodePriceItem(this.AdminContext(), &pb.CreateNodePriceItemRequest{
|
||||
Name: params.Name,
|
||||
Type: userconfigs.PriceTypeBandwidth,
|
||||
BitsFrom: int64(params.MinMB) << 20,
|
||||
BitsTo: int64(params.MaxMB) << 20,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
defer this.CreateLogInfo(codes.NodePriceItem_LogCreateNodePriceItemBandwidth, createResp.NodePriceItemId)
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
//go:build plus
|
||||
|
||||
package items
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type CreateTrafficPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreateTrafficPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreateTrafficPopupAction) RunGet(params struct {
|
||||
}) {
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreateTrafficPopupAction) RunPost(params struct {
|
||||
Name string
|
||||
MinGB uint32
|
||||
MaxGB uint32
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入名称")
|
||||
|
||||
if params.MinGB > 0 && params.MaxGB > 0 && params.MinGB > params.MaxGB {
|
||||
params.MinGB, params.MaxGB = params.MaxGB, params.MinGB
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().NodePriceItemRPC().CreateNodePriceItem(this.AdminContext(), &pb.CreateNodePriceItemRequest{
|
||||
Name: params.Name,
|
||||
Type: userconfigs.PriceTypeTraffic,
|
||||
BitsFrom: int64(params.MinGB) << 33,
|
||||
BitsTo: int64(params.MaxGB) << 33,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
defer this.CreateLogInfo(codes.NodePriceItem_LogCreateNodePriceItemTraffic, createResp.NodePriceItemId)
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
//go:build plus
|
||||
|
||||
package items
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
ItemId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NodePriceItem_LogDeleteNodePriceItem, params.ItemId)
|
||||
|
||||
_, err := this.RPC().NodePriceItemRPC().DeleteNodePriceItem(this.AdminContext(), &pb.DeleteNodePriceItemRequest{NodePriceItemId: params.ItemId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//go:build plus
|
||||
|
||||
package items
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeFinance)).
|
||||
Data("teaMenu", "clusters").
|
||||
Data("teaSubMenu", "region").
|
||||
Prefix("/finance/fee/items").
|
||||
GetPost("/createTrafficPopup", new(CreateTrafficPopupAction)).
|
||||
GetPost("/updateTrafficPopup", new(UpdateTrafficPopupAction)).
|
||||
GetPost("/createBandwidthPopup", new(CreateBandwidthPopupAction)).
|
||||
GetPost("/updateBandwidthPopup", new(UpdateBandwidthPopupAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
//go:build plus
|
||||
|
||||
package items
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdateBandwidthPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateBandwidthPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdateBandwidthPopupAction) RunGet(params struct {
|
||||
ItemId int64
|
||||
}) {
|
||||
itemResp, err := this.RPC().NodePriceItemRPC().FindEnabledNodePriceItem(this.AdminContext(), &pb.FindEnabledNodePriceItemRequest{NodePriceItemId: params.ItemId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var item = itemResp.NodePriceItem
|
||||
if item == nil {
|
||||
this.NotFound("nodePriceItem", params.ItemId)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["item"] = maps.Map{
|
||||
"id": item.Id,
|
||||
"name": item.Name,
|
||||
"minMB": item.BitsFrom / (1 << 20),
|
||||
"maxMB": item.BitsTo / (1 << 20),
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateBandwidthPopupAction) RunPost(params struct {
|
||||
ItemId int64
|
||||
Name string
|
||||
MinMB uint32
|
||||
MaxMB uint32
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NodePriceItem_LogUpdateNodePriceItemBandwidth, params.ItemId)
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入名称")
|
||||
|
||||
if params.MinMB > 0 && params.MaxMB > 0 && params.MinMB > params.MaxMB {
|
||||
params.MinMB, params.MaxMB = params.MaxMB, params.MinMB
|
||||
}
|
||||
|
||||
_, err := this.RPC().NodePriceItemRPC().UpdateNodePriceItem(this.AdminContext(), &pb.UpdateNodePriceItemRequest{
|
||||
NodePriceItemId: params.ItemId,
|
||||
Name: params.Name,
|
||||
BitsFrom: int64(params.MinMB) << 20,
|
||||
BitsTo: int64(params.MaxMB) << 20,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
//go:build plus
|
||||
|
||||
package items
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdateTrafficPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateTrafficPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdateTrafficPopupAction) RunGet(params struct {
|
||||
ItemId int64
|
||||
}) {
|
||||
itemResp, err := this.RPC().NodePriceItemRPC().FindEnabledNodePriceItem(this.AdminContext(), &pb.FindEnabledNodePriceItemRequest{NodePriceItemId: params.ItemId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var item = itemResp.NodePriceItem
|
||||
if item == nil {
|
||||
this.NotFound("nodePriceItem", params.ItemId)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["item"] = maps.Map{
|
||||
"id": item.Id,
|
||||
"name": item.Name,
|
||||
"minGB": item.BitsFrom / (1 << 33),
|
||||
"maxGB": item.BitsTo / (1 << 33),
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateTrafficPopupAction) RunPost(params struct {
|
||||
ItemId int64
|
||||
Name string
|
||||
MinGB uint32
|
||||
MaxGB uint32
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NodePriceItem_LogUpdateNodePriceItemTraffic, params.ItemId)
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入名称")
|
||||
|
||||
if params.MinGB > 0 && params.MaxGB > 0 && params.MinGB > params.MaxGB {
|
||||
params.MinGB, params.MaxGB = params.MaxGB, params.MinGB
|
||||
}
|
||||
|
||||
_, err := this.RPC().NodePriceItemRPC().UpdateNodePriceItem(this.AdminContext(), &pb.UpdateNodePriceItemRequest{
|
||||
NodePriceItemId: params.ItemId,
|
||||
Name: params.Name,
|
||||
BitsFrom: int64(params.MinGB) << 33,
|
||||
BitsTo: int64(params.MaxGB) << 33,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
//go:build plus
|
||||
|
||||
package fee
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/financeutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type TrafficAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *TrafficAction) Init() {
|
||||
this.Nav("", "", "traffic")
|
||||
}
|
||||
|
||||
func (this *TrafficAction) RunGet(params struct{}) {
|
||||
// 财务相关配置
|
||||
config, err := financeutils.ReadPriceConfig(this.AdminContext())
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["config"] = config
|
||||
|
||||
// 所有价格项目
|
||||
itemsResp, err := this.RPC().NodePriceItemRPC().FindAllAvailableNodePriceItems(this.AdminContext(), &pb.FindAllAvailableNodePriceItemsRequest{Type: userconfigs.PriceTypeTraffic})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var itemMaps = []maps.Map{}
|
||||
for _, item := range itemsResp.NodePriceItems {
|
||||
var maxSize string
|
||||
if item.BitsTo == 0 {
|
||||
maxSize = "∞"
|
||||
} else {
|
||||
maxSize = numberutils.FormatBytes(item.BitsTo / 8)
|
||||
}
|
||||
|
||||
itemMaps = append(itemMaps, maps.Map{
|
||||
"id": item.Id,
|
||||
"name": item.Name,
|
||||
"minSize": numberutils.FormatBytes(item.BitsFrom / 8),
|
||||
"maxSize": maxSize,
|
||||
})
|
||||
}
|
||||
this.Data["items"] = itemMaps
|
||||
|
||||
// 所有区域
|
||||
regionsResp, err := this.RPC().NodeRegionRPC().FindAllAvailableNodeRegions(this.AdminContext(), &pb.FindAllAvailableNodeRegionsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var regionMaps = []maps.Map{}
|
||||
for _, region := range regionsResp.NodeRegions {
|
||||
pricesMap := map[string]float32{}
|
||||
if len(region.PricesJSON) > 0 {
|
||||
err = json.Unmarshal(region.PricesJSON, &pricesMap)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
regionMaps = append(regionMaps, maps.Map{
|
||||
"id": region.Id,
|
||||
"isOn": region.IsOn,
|
||||
"name": region.Name,
|
||||
"prices": pricesMap,
|
||||
})
|
||||
}
|
||||
this.Data["regions"] = regionMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
//go:build plus
|
||||
|
||||
package fee
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdatePricePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePricePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdatePricePopupAction) RunGet(params struct {
|
||||
RegionId int64
|
||||
ItemId int64
|
||||
}) {
|
||||
// 区域
|
||||
regionResp, err := this.RPC().NodeRegionRPC().FindEnabledNodeRegion(this.AdminContext(), &pb.FindEnabledNodeRegionRequest{NodeRegionId: params.RegionId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var region = regionResp.NodeRegion
|
||||
if region == nil {
|
||||
this.NotFound("nodeRegion", params.RegionId)
|
||||
return
|
||||
}
|
||||
this.Data["region"] = maps.Map{
|
||||
"id": region.Id,
|
||||
"isOn": region.IsOn,
|
||||
"name": region.Name,
|
||||
}
|
||||
|
||||
// 当前价格
|
||||
var pricesMap = map[string]float32{}
|
||||
if len(region.PricesJSON) > 0 {
|
||||
err = json.Unmarshal(region.PricesJSON, &pricesMap)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
this.Data["price"] = pricesMap[numberutils.FormatInt64(params.ItemId)]
|
||||
|
||||
// 价格项
|
||||
itemResp, err := this.RPC().NodePriceItemRPC().FindEnabledNodePriceItem(this.AdminContext(), &pb.FindEnabledNodePriceItemRequest{NodePriceItemId: params.ItemId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var item = itemResp.NodePriceItem
|
||||
if item == nil {
|
||||
this.NotFound("nodePriceItem", params.ItemId)
|
||||
return
|
||||
}
|
||||
|
||||
var minSize = ""
|
||||
var maxSize = ""
|
||||
|
||||
switch item.Type {
|
||||
case userconfigs.PriceTypeTraffic:
|
||||
minSize = numberutils.FormatBytes(item.BitsFrom / 8)
|
||||
if item.BitsTo > 0 {
|
||||
maxSize = numberutils.FormatBytes(item.BitsTo / 8)
|
||||
} else {
|
||||
maxSize = "∞"
|
||||
}
|
||||
case userconfigs.PriceTypeBandwidth:
|
||||
minSize = numberutils.FormatBits(item.BitsFrom)
|
||||
if item.BitsTo > 0 {
|
||||
maxSize = numberutils.FormatBits(item.BitsTo)
|
||||
} else {
|
||||
maxSize = "∞"
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["item"] = maps.Map{
|
||||
"id": item.Id,
|
||||
"name": item.Name,
|
||||
"type": item.Type,
|
||||
"minSize": minSize,
|
||||
"maxSize": maxSize,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePricePopupAction) RunPost(params struct {
|
||||
RegionId int64
|
||||
ItemId int64
|
||||
Price float32
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.NodeRegionPrice_LogUpdateNodeRegionPrice, params.RegionId, params.ItemId)
|
||||
|
||||
_, err := this.RPC().NodeRegionRPC().UpdateNodeRegionPrice(this.AdminContext(), &pb.UpdateNodeRegionPriceRequest{
|
||||
NodeRegionId: params.RegionId,
|
||||
NodeItemId: params.ItemId,
|
||||
Price: params.Price,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package financeutils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
)
|
||||
|
||||
// ReadPriceConfig 读取价格相关配置
|
||||
func ReadPriceConfig(ctx context.Context) (*userconfigs.UserPriceConfig, error) {
|
||||
rpcClient, err := rpc.SharedRPC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
valueResp, err := rpcClient.SysSettingRPC().ReadSysSetting(ctx, &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeUserPriceConfig})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var valueJSON = valueResp.ValueJSON
|
||||
var config = userconfigs.DefaultUserPriceConfig()
|
||||
if len(valueJSON) > 0 {
|
||||
err = json.Unmarshal(valueJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package income
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type DailyAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DailyAction) Init() {
|
||||
this.Nav("", "", "monthly")
|
||||
}
|
||||
|
||||
func (this *DailyAction) RunGet(params struct {
|
||||
Month string
|
||||
}) {
|
||||
if len(params.Month) == 0 {
|
||||
params.Month = timeutil.Format("Y-m")
|
||||
}
|
||||
|
||||
this.Data["month"] = params.Month
|
||||
|
||||
var dayFrom = params.Month + "-01"
|
||||
var dayTo = params.Month + "-32"
|
||||
|
||||
statsResp, err := this.RPC().UserAccountDailyStatRPC().ListUserAccountDailyStats(this.AdminContext(), &pb.ListUserAccountDailyStatsRequest{
|
||||
DayFrom: dayFrom,
|
||||
DayTo: dayTo,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var statMaps = []maps.Map{}
|
||||
for _, stat := range statsResp.Stats {
|
||||
if stat.Day > timeutil.Format("Ymd") {
|
||||
continue
|
||||
}
|
||||
|
||||
statMaps = append(statMaps, maps.Map{
|
||||
"day": stat.Day[:4] + "-" + stat.Day[4:6] + "-" + stat.Day[6:],
|
||||
"income": stat.Income,
|
||||
"expense": stat.Expense,
|
||||
})
|
||||
}
|
||||
this.Data["stats"] = statMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package income
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "daily")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
DayFrom string
|
||||
DayTo string
|
||||
}) {
|
||||
var dayFrom = params.DayFrom
|
||||
var dayTo = params.DayTo
|
||||
if len(dayFrom) == 0 {
|
||||
dayFrom = timeutil.Format("Y-m-d", time.Now().AddDate(0, 0, -14))
|
||||
}
|
||||
if len(dayTo) == 0 {
|
||||
dayTo = timeutil.Format("Y-m-d")
|
||||
}
|
||||
if dayFrom > dayTo {
|
||||
dayFrom, dayTo = dayTo, dayFrom
|
||||
}
|
||||
this.Data["dayFrom"] = dayFrom
|
||||
this.Data["dayTo"] = dayTo
|
||||
|
||||
statsResp, err := this.RPC().UserAccountDailyStatRPC().ListUserAccountDailyStats(this.AdminContext(), &pb.ListUserAccountDailyStatsRequest{
|
||||
DayFrom: dayFrom,
|
||||
DayTo: dayTo,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var statMaps = []maps.Map{}
|
||||
for _, stat := range statsResp.Stats {
|
||||
statMaps = append(statMaps, maps.Map{
|
||||
"day": stat.Day[:4] + "-" + stat.Day[4:6] + "-" + stat.Day[6:],
|
||||
"income": stat.Income,
|
||||
"expense": stat.Expense,
|
||||
})
|
||||
}
|
||||
this.Data["stats"] = statMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
//go:build plus
|
||||
|
||||
package income
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeFinance)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeFinance)).
|
||||
Data("teaMenu", "finance").
|
||||
Data("teaSubMenu", "income").
|
||||
|
||||
// 财务管理
|
||||
Prefix("/finance/income").
|
||||
Get("", new(IndexAction)).
|
||||
Get("/monthly", new(MonthlyAction)).
|
||||
Get("/daily", new(DailyAction)).
|
||||
|
||||
//
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package income
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
type MonthlyAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *MonthlyAction) Init() {
|
||||
this.Nav("", "", "monthly")
|
||||
}
|
||||
|
||||
func (this *MonthlyAction) RunGet(params struct {
|
||||
DayFrom string
|
||||
DayTo string
|
||||
}) {
|
||||
var dayFrom = params.DayFrom
|
||||
var dayTo = params.DayTo
|
||||
if len(dayFrom) == 0 {
|
||||
dayFrom = timeutil.Format("Y-m-01", time.Now().AddDate(0, -12, 0))
|
||||
}
|
||||
if len(dayTo) == 0 {
|
||||
dayTo = timeutil.Format("Y-m-d")
|
||||
}
|
||||
if dayFrom > dayTo {
|
||||
dayFrom, dayTo = dayTo, dayFrom
|
||||
}
|
||||
this.Data["dayFrom"] = dayFrom
|
||||
this.Data["dayTo"] = dayTo
|
||||
|
||||
statsResp, err := this.RPC().UserAccountDailyStatRPC().ListUserAccountMonthlyStats(this.AdminContext(), &pb.ListUserAccountMonthlyStatsRequest{
|
||||
DayFrom: dayFrom,
|
||||
DayTo: dayTo,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var statMaps = []maps.Map{}
|
||||
for _, stat := range statsResp.Stats {
|
||||
statMaps = append(statMaps, maps.Map{
|
||||
"month": stat.Month[:4] + "-" + stat.Month[4:6],
|
||||
"income": stat.Income,
|
||||
"expense": stat.Expense,
|
||||
})
|
||||
}
|
||||
this.Data["stats"] = statMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
16
EdgeAdmin/internal/web/actions/default/finance/index.go
Normal file
16
EdgeAdmin/internal/web/actions/default/finance/index.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package finance
|
||||
|
||||
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
// TODO 暂时先跳转到账单页,将来做成Dashboard
|
||||
this.RedirectURL("/finance/bills")
|
||||
}
|
||||
41
EdgeAdmin/internal/web/actions/default/finance/init.go
Normal file
41
EdgeAdmin/internal/web/actions/default/finance/init.go
Normal file
@@ -0,0 +1,41 @@
|
||||
//go:build plus
|
||||
|
||||
package finance
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/fee"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/users"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeFinance)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeFinance)).
|
||||
|
||||
// 财务管理
|
||||
Prefix("/finance").
|
||||
Get("", new(IndexAction)).
|
||||
Data("teaMenu", "finance").
|
||||
|
||||
// 计费设置
|
||||
Prefix("/finance/fee").
|
||||
Data("teaSubMenu", "fee").
|
||||
GetPost("", new(fee.IndexAction)).
|
||||
Get("/traffic", new(fee.TrafficAction)).
|
||||
Get("/bandwidth", new(fee.BandwidthAction)).
|
||||
GetPost("/updatePricePopup", new(fee.UpdatePricePopupAction)).
|
||||
GetPost("/calculator", new(fee.CalculatorAction)).
|
||||
|
||||
// 用户
|
||||
Prefix("/finance/users").
|
||||
Post("/options", new(users.OptionsAction)).
|
||||
|
||||
//
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
84
EdgeAdmin/internal/web/actions/default/finance/logs/index.go
Normal file
84
EdgeAdmin/internal/web/actions/default/finance/logs/index.go
Normal file
@@ -0,0 +1,84 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
|
||||
package logs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
Keyword string
|
||||
EventType string
|
||||
}) {
|
||||
this.Data["keyword"] = params.Keyword
|
||||
this.Data["eventType"] = params.EventType
|
||||
|
||||
// 所有事件类型
|
||||
this.Data["events"] = userconfigs.FindAllAccountEventTypes()
|
||||
|
||||
// 数量
|
||||
countResp, err := this.RPC().UserAccountLogRPC().CountUserAccountLogs(this.AdminContext(), &pb.CountUserAccountLogsRequest{
|
||||
Keyword: params.Keyword,
|
||||
EventType: params.EventType,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var count = countResp.Count
|
||||
var page = this.NewPage(count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
logsResp, err := this.RPC().UserAccountLogRPC().ListUserAccountLogs(this.AdminContext(), &pb.ListUserAccountLogsRequest{
|
||||
Keyword: params.Keyword,
|
||||
EventType: params.EventType,
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var logMaps = []maps.Map{}
|
||||
for _, log := range logsResp.UserAccountLogs {
|
||||
var userMap = maps.Map{}
|
||||
if log.User != nil {
|
||||
userMap = maps.Map{
|
||||
"id": log.User.Id,
|
||||
"username": log.User.Username,
|
||||
"fullname": log.User.Fullname,
|
||||
}
|
||||
}
|
||||
|
||||
logMaps = append(logMaps, maps.Map{
|
||||
"id": log.Id,
|
||||
"description": log.Description,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", log.CreatedAt),
|
||||
"delta": log.Delta,
|
||||
"deltaFormatted": numberutils.FormatFloat(log.Delta, 2),
|
||||
"deltaFrozen": log.DeltaFrozen,
|
||||
"total": log.Total,
|
||||
"totalFormatted": numberutils.FormatFloat(log.Total, 2),
|
||||
"totalFrozen": log.TotalFrozen,
|
||||
"event": userconfigs.FindAccountEvent(log.EventType),
|
||||
"user": userMap,
|
||||
"accountId": log.UserAccountId,
|
||||
})
|
||||
}
|
||||
this.Data["logs"] = logMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
27
EdgeAdmin/internal/web/actions/default/finance/logs/init.go
Normal file
27
EdgeAdmin/internal/web/actions/default/finance/logs/init.go
Normal file
@@ -0,0 +1,27 @@
|
||||
//go:build plus
|
||||
|
||||
package logs
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeFinance)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeFinance)).
|
||||
Data("teaMenu", "finance").
|
||||
Data("teaSubMenu", "logs").
|
||||
|
||||
// 财务管理
|
||||
Prefix("/finance/logs").
|
||||
Get("", new(IndexAction)).
|
||||
|
||||
//
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
109
EdgeAdmin/internal/web/actions/default/finance/orders/index.go
Normal file
109
EdgeAdmin/internal/web/actions/default/finance/orders/index.go
Normal file
@@ -0,0 +1,109 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package orders
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/orders/orderutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "order")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
UserId int64
|
||||
Status string
|
||||
Keyword string
|
||||
}) {
|
||||
this.Data["userId"] = params.UserId
|
||||
this.Data["status"] = params.Status
|
||||
this.Data["keyword"] = params.Keyword
|
||||
|
||||
// 是否支持支付
|
||||
orderConfig, err := orderutils.FindOrderConfig(this.AdminContext())
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["enablePay"] = orderConfig.EnablePay
|
||||
|
||||
// 订单数量
|
||||
countResp, err := this.RPC().UserOrderRPC().CountEnabledUserOrders(this.AdminContext(), &pb.CountEnabledUserOrdersRequest{
|
||||
UserId: params.UserId,
|
||||
Status: params.Status,
|
||||
Keyword: params.Keyword,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var count = countResp.Count
|
||||
var page = this.NewPage(count)
|
||||
this.Data["page"] = page.AsHTML()
|
||||
|
||||
// 订单列表
|
||||
ordersResp, err := this.RPC().UserOrderRPC().ListEnabledUserOrders(this.AdminContext(), &pb.ListEnabledUserOrdersRequest{
|
||||
UserId: params.UserId,
|
||||
Status: params.Status,
|
||||
Keyword: params.Keyword,
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var orderMaps = []maps.Map{}
|
||||
for _, order := range ordersResp.UserOrders {
|
||||
// user
|
||||
var userMap = maps.Map{
|
||||
"id": 0,
|
||||
}
|
||||
if order.User != nil {
|
||||
userMap = maps.Map{
|
||||
"id": order.User.Id,
|
||||
"fullname": order.User.Fullname,
|
||||
"username": order.User.Username,
|
||||
}
|
||||
}
|
||||
|
||||
// method
|
||||
var methodMap = maps.Map{
|
||||
"id": 0,
|
||||
}
|
||||
if order.OrderMethod != nil {
|
||||
methodMap = maps.Map{
|
||||
"id": order.OrderMethod.Id,
|
||||
"name": order.OrderMethod.Name,
|
||||
}
|
||||
}
|
||||
|
||||
orderMaps = append(orderMaps, maps.Map{
|
||||
"code": order.Code,
|
||||
"type": order.Type,
|
||||
"typeName": userconfigs.FindOrderTypeName(order.Type),
|
||||
"status": order.Status,
|
||||
"statusName": userconfigs.FindOrderStatusName(order.Status),
|
||||
"amount": order.Amount,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", order.CreatedAt),
|
||||
"user": userMap,
|
||||
"method": methodMap,
|
||||
})
|
||||
}
|
||||
this.Data["orders"] = orderMaps
|
||||
|
||||
// 所有状态
|
||||
this.Data["statusList"] = userconfigs.FindAllOrderStatusList()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
//go:build plus
|
||||
|
||||
package orders
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/orders/methods"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/orders/methods/method"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/orders/order"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeFinance)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeFinance)).
|
||||
Data("teaMenu", "finance").
|
||||
Data("teaSubMenu", "orders").
|
||||
|
||||
// 订单列表
|
||||
Prefix("/finance/orders").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/setting", new(SettingAction)).
|
||||
|
||||
// 单个订单
|
||||
Prefix("/finance/orders/order").
|
||||
Get("", new(order.IndexAction)).
|
||||
Post("/finish", new(order.FinishAction)).
|
||||
|
||||
// 支付方式列表
|
||||
Prefix("/finance/orders/methods").
|
||||
Get("", new(methods.IndexAction)).
|
||||
GetPost("/createPopup", new(methods.CreatePopupAction)).
|
||||
|
||||
// 单个支付方式
|
||||
Prefix("/finance/orders/methods/method").
|
||||
Get("", new(method.IndexAction)).
|
||||
GetPost("/update", new(method.UpdateAction)).
|
||||
Post("/delete", new(method.DeleteAction)).
|
||||
|
||||
//
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package methods
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
this.Nav("", "", "method")
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct{}) {
|
||||
this.Data["presetMethods"] = userconfigs.FindAllPresetPayMethods()
|
||||
this.Data["clientTypes"] = userconfigs.FindAllPayClientTypes()
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
Name string
|
||||
Code string
|
||||
Description string
|
||||
ClientType string
|
||||
QrcodeTitle string
|
||||
|
||||
ParentCode string
|
||||
|
||||
// 自定义支付方式
|
||||
Url string
|
||||
|
||||
// Alipay
|
||||
ParamsAlipayAppId string
|
||||
ParamsAlipayPrivateKey string
|
||||
ParamsAlipayAppPublicCert string
|
||||
ParamsAlipayPublicCert string
|
||||
ParamsAlipayRootCert string
|
||||
ParamsAlipayProductCode string
|
||||
ParamsAlipayIsSandbox bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
var methodId int64
|
||||
defer func() {
|
||||
this.CreateLogInfo(codes.OrderMethod_LogCreateOrderMethod, methodId)
|
||||
}()
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入支付方式名称").
|
||||
Field("code", params.Code).
|
||||
Require("请输入支付方式代号").
|
||||
Match("^\\w+$", "代号中只能包含数字、字母和下划线").
|
||||
Field("description", params.Description).
|
||||
Require("请输入支付方式描述")
|
||||
|
||||
// 检查代号是否被占用
|
||||
methodResp, err := this.RPC().OrderMethodRPC().FindEnabledOrderMethodWithCode(this.AdminContext(), &pb.FindEnabledOrderMethodWithCodeRequest{Code: params.Code})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if methodResp.OrderMethod != nil {
|
||||
this.Fail("代号 '" + params.Code + "' 已经被别的支付方式使用,请换一个")
|
||||
}
|
||||
|
||||
var payParams userconfigs.PayMethodParams
|
||||
switch params.ParentCode {
|
||||
case "":
|
||||
params.Must.
|
||||
Field("url", params.Url).
|
||||
Require("请输入支付URL").
|
||||
Match("^(?i)(http|https)://", "请输入正确的支付URL")
|
||||
case userconfigs.PayMethodAlipay:
|
||||
params.Must.
|
||||
Field("paramsAlipayAppId", params.ParamsAlipayAppId).
|
||||
Require("请输入APPID").
|
||||
Field("paramsAlipayPrivateKey", params.ParamsAlipayPrivateKey).
|
||||
Require("请输入私钥").
|
||||
Field("paramsAlipayAppPublicCert", params.ParamsAlipayAppPublicCert).
|
||||
Require("请输入应用公钥证书").
|
||||
Field("paramsAlipayPublicCert", params.ParamsAlipayPublicCert).
|
||||
Require("请输入支付宝公钥证书").
|
||||
Field("paramsAlipayRootCert", params.ParamsAlipayRootCert).
|
||||
Require("请输入支付宝根证书").
|
||||
Field("paramsAlipayProductCode", params.ParamsAlipayProductCode).
|
||||
Require("请输入产品代号")
|
||||
|
||||
payParams = &userconfigs.AlipayPayMethodParams{
|
||||
IsSandbox: params.ParamsAlipayIsSandbox,
|
||||
AppId: params.ParamsAlipayAppId,
|
||||
PrivateKey: params.ParamsAlipayPrivateKey,
|
||||
AppPublicCert: params.ParamsAlipayAppPublicCert,
|
||||
AlipayPublicCert: params.ParamsAlipayPublicCert,
|
||||
AlipayRootCert: params.ParamsAlipayRootCert,
|
||||
ProductCode: params.ParamsAlipayProductCode,
|
||||
}
|
||||
}
|
||||
|
||||
if payParams != nil {
|
||||
err = payParams.Init()
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
payParamsJSON, err := json.Marshal(payParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().OrderMethodRPC().CreateOrderMethod(this.AdminContext(), &pb.CreateOrderMethodRequest{
|
||||
Name: params.Name,
|
||||
Code: params.Code,
|
||||
Description: params.Description,
|
||||
Url: params.Url,
|
||||
ParentCode: params.ParentCode,
|
||||
ParamsJSON: payParamsJSON,
|
||||
ClientType: params.ClientType,
|
||||
QrcodeTitle: params.QrcodeTitle,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
methodId = createResp.OrderMethodId
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package methods
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/orders/orderutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "method")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
// 是否支持支付
|
||||
orderConfig, err := orderutils.FindOrderConfig(this.AdminContext())
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["enablePay"] = orderConfig.EnablePay
|
||||
|
||||
// 所有的支付方式
|
||||
methodsResp, err := this.RPC().OrderMethodRPC().FindAllEnabledOrderMethods(this.AdminContext(), &pb.FindAllEnabledOrderMethodsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var methodMaps = []maps.Map{}
|
||||
for _, method := range methodsResp.OrderMethods {
|
||||
var parentName = ""
|
||||
if len(method.ParentCode) > 0 {
|
||||
var parentMethod = userconfigs.FindPresetPayMethodWithCode(method.ParentCode)
|
||||
if parentMethod != nil {
|
||||
parentName = parentMethod.Name
|
||||
}
|
||||
}
|
||||
|
||||
methodMaps = append(methodMaps, maps.Map{
|
||||
"id": method.Id,
|
||||
"name": method.Name,
|
||||
"code": method.Code,
|
||||
"parentCode": method.ParentCode,
|
||||
"parentName": parentName,
|
||||
"description": method.Description,
|
||||
"url": method.Url,
|
||||
"isOn": method.IsOn,
|
||||
"clientType": method.ClientType,
|
||||
"clientTypeName": userconfigs.FindPayClientTypeName(method.ClientType),
|
||||
})
|
||||
}
|
||||
this.Data["methods"] = methodMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package method
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
MethodId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.OrderMethod_LogDeleteOrderMethod, params.MethodId)
|
||||
|
||||
_, err := this.RPC().OrderMethodRPC().DeleteOrderMethod(this.AdminContext(), &pb.DeleteOrderMethodRequest{OrderMethodId: params.MethodId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package method
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
MethodId int64
|
||||
}) {
|
||||
methodResp, err := this.RPC().OrderMethodRPC().FindEnabledOrderMethod(this.AdminContext(), &pb.FindEnabledOrderMethodRequest{OrderMethodId: params.MethodId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var method = methodResp.OrderMethod
|
||||
if method == nil {
|
||||
this.NotFound("orderMethod", params.MethodId)
|
||||
return
|
||||
}
|
||||
|
||||
// 父级支付方式和参数
|
||||
var parentCode = method.ParentCode
|
||||
var parentName = ""
|
||||
var payParams any
|
||||
var payNotifyURL = ""
|
||||
if len(parentCode) > 0 {
|
||||
var parentDef = userconfigs.FindPresetPayMethodWithCode(parentCode)
|
||||
if parentDef != nil {
|
||||
parentName = parentDef.Name
|
||||
|
||||
payParams, err = userconfigs.DecodePayMethodParams(parentCode, method.Params)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(parentDef.NotifyURL) > 0 {
|
||||
accessAddrResp, err := this.RPC().UserNodeRPC().FindUserNodeAccessAddr(this.AdminContext(), &pb.FindUserNodeAccessAddrRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var accessAddr = accessAddrResp.AccessAddr
|
||||
payNotifyURL = strings.ReplaceAll(parentDef.NotifyURL, "${baseAddr}", accessAddr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 终端
|
||||
if len(method.ClientType) == 0 {
|
||||
method.ClientType = userconfigs.PayClientTypeAll
|
||||
}
|
||||
var clientTypeName = ""
|
||||
var clientTypeDescription = ""
|
||||
var clientType = userconfigs.FindPayClientType(method.ClientType)
|
||||
if clientType != nil {
|
||||
clientTypeName = clientType.Name
|
||||
clientTypeDescription = clientType.Description
|
||||
}
|
||||
|
||||
this.Data["method"] = maps.Map{
|
||||
"id": method.Id,
|
||||
"name": method.Name,
|
||||
"code": method.Code,
|
||||
"description": method.Description,
|
||||
"secret": method.Secret,
|
||||
"isOn": method.IsOn,
|
||||
|
||||
"parentCode": parentCode,
|
||||
"parentName": parentName,
|
||||
"payNotifyURL": payNotifyURL,
|
||||
"url": method.Url, // 自定义
|
||||
"params": payParams, // 非自定义
|
||||
|
||||
"clientType": method.ClientType,
|
||||
"clientTypeName": clientTypeName,
|
||||
"clientTypeDescription": clientTypeDescription,
|
||||
"qrcodeTitle": method.QrcodeTitle,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package method
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdateAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdateAction) Init() {
|
||||
this.Nav("", "", "update")
|
||||
}
|
||||
|
||||
func (this *UpdateAction) RunGet(params struct {
|
||||
MethodId int64
|
||||
}) {
|
||||
methodResp, err := this.RPC().OrderMethodRPC().FindEnabledOrderMethod(this.AdminContext(), &pb.FindEnabledOrderMethodRequest{OrderMethodId: params.MethodId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var method = methodResp.OrderMethod
|
||||
if method == nil {
|
||||
this.NotFound("orderMethod", params.MethodId)
|
||||
return
|
||||
}
|
||||
|
||||
// 父级支付方式和参数
|
||||
var parentCode = method.ParentCode
|
||||
var parentName = ""
|
||||
var payParams any
|
||||
if len(parentCode) > 0 {
|
||||
var parentDef = userconfigs.FindPresetPayMethodWithCode(parentCode)
|
||||
if parentDef != nil {
|
||||
parentName = parentDef.Name
|
||||
|
||||
payParams, err = userconfigs.DecodePayMethodParams(parentCode, method.Params)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 支持的终端类型
|
||||
this.Data["clientTypes"] = userconfigs.FindAllPayClientTypes()
|
||||
if len(method.ClientType) == 0 {
|
||||
method.ClientType = userconfigs.PayClientTypeAll
|
||||
}
|
||||
|
||||
this.Data["method"] = maps.Map{
|
||||
"id": method.Id,
|
||||
"name": method.Name,
|
||||
"code": method.Code,
|
||||
"description": method.Description,
|
||||
"url": method.Url,
|
||||
"isOn": method.IsOn,
|
||||
"parentCode": method.ParentCode,
|
||||
"parentName": parentName,
|
||||
"params": payParams,
|
||||
"clientType": method.ClientType,
|
||||
"qrcodeTitle": method.QrcodeTitle,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdateAction) RunPost(params struct {
|
||||
MethodId int64
|
||||
Name string
|
||||
Code string
|
||||
Description string
|
||||
IsOn bool
|
||||
ClientType string
|
||||
QrcodeTitle string
|
||||
|
||||
// 自定义支付方式
|
||||
Url string
|
||||
|
||||
// Alipay
|
||||
ParamsAlipayAppId string
|
||||
ParamsAlipayPrivateKey string
|
||||
ParamsAlipayAppPublicCert string
|
||||
ParamsAlipayPublicCert string
|
||||
ParamsAlipayRootCert string
|
||||
ParamsAlipayProductCode string
|
||||
ParamsAlipayIsSandbox bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.OrderMethod_LogUpdateOrderMethod, params.MethodId)
|
||||
|
||||
params.Must.
|
||||
Field("name", params.Name).
|
||||
Require("请输入支付方式名称").
|
||||
Field("code", params.Code).
|
||||
Require("请输入支付方式代号").
|
||||
Match("^\\w+$", "代号中只能包含数字、字母和下划线").
|
||||
Field("description", params.Description).
|
||||
Require("请输入支付方式描述")
|
||||
|
||||
// 检查代号是否被占用
|
||||
methodWithCodeResp, err := this.RPC().OrderMethodRPC().FindEnabledOrderMethodWithCode(this.AdminContext(), &pb.FindEnabledOrderMethodWithCodeRequest{Code: params.Code})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if methodWithCodeResp.OrderMethod != nil && methodWithCodeResp.OrderMethod.Id != params.MethodId {
|
||||
this.Fail("代号 '" + params.Code + "' 已经被别的支付方式使用,请换一个")
|
||||
}
|
||||
|
||||
// 当前支付方式
|
||||
methodResp, err := this.RPC().OrderMethodRPC().FindEnabledOrderMethod(this.AdminContext(), &pb.FindEnabledOrderMethodRequest{OrderMethodId: params.MethodId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var method = methodResp.OrderMethod
|
||||
if method == nil {
|
||||
this.Fail("找不到要修改的支付方式")
|
||||
}
|
||||
|
||||
var payParams userconfigs.PayMethodParams
|
||||
switch method.ParentCode {
|
||||
case "":
|
||||
params.Must.
|
||||
Field("url", params.Url).
|
||||
Require("请输入支付URL").
|
||||
Match("^(?i)(http|https)://", "请输入正确的支付URL")
|
||||
case userconfigs.PayMethodAlipay:
|
||||
params.Must.
|
||||
Field("paramsAlipayAppId", params.ParamsAlipayAppId).
|
||||
Require("请输入APPID").
|
||||
Field("paramsAlipayPrivateKey", params.ParamsAlipayPrivateKey).
|
||||
Require("请输入私钥").
|
||||
Field("paramsAlipayAppPublicCert", params.ParamsAlipayAppPublicCert).
|
||||
Require("请输入应用公钥证书").
|
||||
Field("paramsAlipayPublicCert", params.ParamsAlipayPublicCert).
|
||||
Require("请输入支付宝公钥证书").
|
||||
Field("paramsAlipayRootCert", params.ParamsAlipayRootCert).
|
||||
Require("请输入支付宝根证书").
|
||||
Field("paramsAlipayProductCode", params.ParamsAlipayProductCode).
|
||||
Require("请输入产品代号")
|
||||
|
||||
payParams = &userconfigs.AlipayPayMethodParams{
|
||||
IsSandbox: params.ParamsAlipayIsSandbox,
|
||||
AppId: params.ParamsAlipayAppId,
|
||||
PrivateKey: params.ParamsAlipayPrivateKey,
|
||||
AppPublicCert: params.ParamsAlipayAppPublicCert,
|
||||
AlipayPublicCert: params.ParamsAlipayPublicCert,
|
||||
AlipayRootCert: params.ParamsAlipayRootCert,
|
||||
ProductCode: params.ParamsAlipayProductCode,
|
||||
}
|
||||
}
|
||||
|
||||
if payParams != nil {
|
||||
err = payParams.Init()
|
||||
if err != nil {
|
||||
this.Fail("配置校验失败:" + err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
payParamsJSON, err := json.Marshal(payParams)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().OrderMethodRPC().UpdateOrderMethod(this.AdminContext(), &pb.UpdateOrderMethodRequest{
|
||||
OrderMethodId: params.MethodId,
|
||||
Name: params.Name,
|
||||
Code: params.Code,
|
||||
Description: params.Description,
|
||||
Url: params.Url,
|
||||
ParamsJSON: payParamsJSON,
|
||||
IsOn: params.IsOn,
|
||||
ClientType: params.ClientType,
|
||||
QrcodeTitle: params.QrcodeTitle,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package order
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type FinishAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *FinishAction) RunPost(params struct {
|
||||
OrderCode string
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.UserOrder_LogFinishUserOrder, params.OrderCode)
|
||||
|
||||
_, err := this.RPC().UserOrderRPC().FinishUserOrder(this.AdminContext(), &pb.FinishUserOrderRequest{Code: params.OrderCode})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package order
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "order")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
OrderCode string
|
||||
}) {
|
||||
orderResp, err := this.RPC().UserOrderRPC().FindEnabledUserOrder(this.AdminContext(), &pb.FindEnabledUserOrderRequest{Code: params.OrderCode})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var order = orderResp.UserOrder
|
||||
if order == nil {
|
||||
this.ErrorPage(errors.New("order with code '" + params.OrderCode + "' not found"))
|
||||
return
|
||||
}
|
||||
|
||||
// user
|
||||
var userMap = maps.Map{
|
||||
"id": 0,
|
||||
}
|
||||
if order.User != nil {
|
||||
userMap = maps.Map{
|
||||
"id": order.User.Id,
|
||||
"fullname": order.User.Fullname,
|
||||
"username": order.User.Username,
|
||||
}
|
||||
}
|
||||
|
||||
// method
|
||||
var methodMap = maps.Map{
|
||||
"id": 0,
|
||||
}
|
||||
if order.OrderMethod != nil {
|
||||
methodMap = maps.Map{
|
||||
"id": order.OrderMethod.Id,
|
||||
"name": order.OrderMethod.Name,
|
||||
}
|
||||
}
|
||||
|
||||
this.Data["order"] = maps.Map{
|
||||
"code": order.Code,
|
||||
"type": order.Type,
|
||||
"typeName": userconfigs.FindOrderTypeName(order.Type),
|
||||
"status": order.Status,
|
||||
"statusName": userconfigs.FindOrderStatusName(order.Status),
|
||||
"amount": order.Amount,
|
||||
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", order.CreatedAt),
|
||||
"cancelledTime": timeutil.FormatTime("Y-m-d H:i:s", order.CancelledAt),
|
||||
"finishedTime": timeutil.FormatTime("Y-m-d H:i:s", order.FinishedAt),
|
||||
"isExpired": order.IsExpired,
|
||||
"user": userMap,
|
||||
"method": methodMap,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package orderutils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
)
|
||||
|
||||
// FindOrderConfig 读取订单设置
|
||||
func FindOrderConfig(ctx context.Context) (*userconfigs.UserOrderConfig, error) {
|
||||
rpcClient, err := rpc.SharedRPC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := rpcClient.SysSettingRPC().ReadSysSetting(ctx, &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeUserOrderConfig})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(resp.ValueJSON) == 0 {
|
||||
return userconfigs.DefaultUserOrderConfig(), nil
|
||||
}
|
||||
|
||||
var config = userconfigs.DefaultUserOrderConfig()
|
||||
err = json.Unmarshal(resp.ValueJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
110
EdgeAdmin/internal/web/actions/default/finance/orders/setting.go
Normal file
110
EdgeAdmin/internal/web/actions/default/finance/orders/setting.go
Normal file
@@ -0,0 +1,110 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package orders
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type SettingAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *SettingAction) Init() {
|
||||
this.Nav("", "", "setting")
|
||||
}
|
||||
|
||||
func (this *SettingAction) RunGet(params struct{}) {
|
||||
// 配置
|
||||
configResp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeUserOrderConfig})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var config = userconfigs.DefaultUserOrderConfig()
|
||||
if len(configResp.ValueJSON) > 0 {
|
||||
err = json.Unmarshal(configResp.ValueJSON, config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
this.Data["config"] = config
|
||||
|
||||
// 当前可用支付方式数量
|
||||
methodsResp, err := this.RPC().OrderMethodRPC().FindAllAvailableOrderMethods(this.AdminContext(), &pb.FindAllAvailableOrderMethodsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["hasValidMethods"] = len(methodsResp.OrderMethods) > 0
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *SettingAction) RunPost(params struct {
|
||||
EnablePay bool
|
||||
DisablePageHTML string
|
||||
OrderLifeJSON []byte
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.Finance_LogUpdateUserOrderConfig)
|
||||
|
||||
// 原有配置
|
||||
configResp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeUserOrderConfig})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var config = userconfigs.DefaultUserOrderConfig()
|
||||
if len(configResp.ValueJSON) > 0 {
|
||||
err = json.Unmarshal(configResp.ValueJSON, config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
config.EnablePay = params.EnablePay
|
||||
config.DisablePageHTML = params.DisablePageHTML
|
||||
|
||||
if len(params.OrderLifeJSON) > 0 {
|
||||
var lifeDuration = &shared.TimeDuration{}
|
||||
err = json.Unmarshal(params.OrderLifeJSON, lifeDuration)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if lifeDuration.Count <= 0 {
|
||||
this.Fail("订单过期时间必须是个有效值")
|
||||
}
|
||||
config.OrderLife = lifeDuration
|
||||
}
|
||||
|
||||
configJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().SysSettingRPC().UpdateSysSetting(this.AdminContext(), &pb.UpdateSysSettingRequest{
|
||||
Code: systemconfigs.SettingCodeUserOrderConfig,
|
||||
ValueJSON: configJSON,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package packages
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct{}) {
|
||||
this.Data["unitOptions"] = []maps.Map{
|
||||
{
|
||||
"code": userconfigs.TrafficPackageSizeUnitGB,
|
||||
"name": "GiB",
|
||||
},
|
||||
{
|
||||
"code": userconfigs.TrafficPackageSizeUnitTB,
|
||||
"name": "TiB",
|
||||
},
|
||||
{
|
||||
"code": userconfigs.TrafficPackageSizeUnitPB,
|
||||
"name": "PiB",
|
||||
},
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
Size int32
|
||||
Unit string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
var packageId int64
|
||||
defer func() {
|
||||
this.CreateLogInfo(codes.TrafficPackage_LogCreateTrafficPackage, packageId)
|
||||
}()
|
||||
|
||||
if params.Size <= 0 {
|
||||
this.FailField("size", "请输入正确的流量包尺寸")
|
||||
return
|
||||
}
|
||||
|
||||
// 限制最大值
|
||||
if params.Unit == userconfigs.TrafficPackageSizeUnitPB && params.Size > 8000 {
|
||||
this.FailField("size", "流量尺寸不能超过8000PB")
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().TrafficPackageRPC().CreateTrafficPackage(this.AdminContext(), &pb.CreateTrafficPackageRequest{
|
||||
Size: params.Size,
|
||||
Unit: params.Unit,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
packageId = createResp.TrafficPackageId
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package packages
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
PackageId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.TrafficPackage_LogDeleteTrafficPackage, params.PackageId)
|
||||
|
||||
_, err := this.RPC().TrafficPackageRPC().DeleteTrafficPackage(this.AdminContext(), &pb.DeleteTrafficPackageRequest{TrafficPackageId: params.PackageId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package packages
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/financeutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "index")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
// 是否已启用
|
||||
config, err := financeutils.ReadPriceConfig(this.AdminContext())
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["enableTrafficPackages"] = config != nil && config.EnableTrafficPackages
|
||||
|
||||
// 流量包列表
|
||||
packagesResp, err := this.RPC().TrafficPackageRPC().FindAllTrafficPackages(this.AdminContext(), &pb.FindAllTrafficPackagesRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var packageMaps = []maps.Map{}
|
||||
for _, p := range packagesResp.TrafficPackages {
|
||||
// prices
|
||||
countPricesResp, err := this.RPC().TrafficPackagePriceRPC().CountTrafficPackagePrices(this.AdminContext(), &pb.CountTrafficPackagePricesRequest{TrafficPackageId: p.Id})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
packageMaps = append(packageMaps, maps.Map{
|
||||
"id": p.Id,
|
||||
"size": p.Size,
|
||||
"unit": strings.ToUpper(p.Unit),
|
||||
"isOn": p.IsOn,
|
||||
"countPrices": countPricesResp.Count,
|
||||
})
|
||||
}
|
||||
this.Data["packages"] = packageMaps
|
||||
|
||||
// 所有区域
|
||||
regionsResp, err := this.RPC().NodeRegionRPC().FindAllAvailableNodeRegions(this.AdminContext(), &pb.FindAllAvailableNodeRegionsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 有效期
|
||||
periodsResp, err := this.RPC().TrafficPackagePeriodRPC().FindAllAvailableTrafficPackagePeriods(this.AdminContext(), &pb.FindAllAvailableTrafficPackagePeriodsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["totalPriceItems"] = len(regionsResp.NodeRegions) * len(periodsResp.TrafficPackagePeriods)
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
//go:build plus
|
||||
|
||||
package packages
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/plus"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/packages/periods"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/packages/periods/period"
|
||||
userpackages "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/packages/user-packages"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
|
||||
"github.com/iwind/TeaGo"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||
server.
|
||||
Helper(plus.NewHelper(plus.ComponentCodeFinance)).
|
||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeFinance)).
|
||||
Data("teaMenu", "finance").
|
||||
Data("teaSubMenu", "package").
|
||||
|
||||
// 流量包
|
||||
Prefix("/finance/packages").
|
||||
Get("", new(IndexAction)).
|
||||
GetPost("/createPopup", new(CreatePopupAction)).
|
||||
GetPost("/updatePopup", new(UpdatePopupAction)).
|
||||
Post("/delete", new(DeleteAction)).
|
||||
GetPost("/updatePricesPopup", new(UpdatePricesPopupAction)).
|
||||
Post("/updatePrice", new(UpdatePriceAction)).
|
||||
|
||||
// 流量包有效期
|
||||
Prefix("/finance/packages/periods").
|
||||
Get("", new(periods.IndexAction)).
|
||||
GetPost("/createPopup", new(periods.CreatePopupAction)).
|
||||
|
||||
// 流量包有效期详情
|
||||
Prefix("/finance/packages/periods/period").
|
||||
GetPost("/updatePopup", new(period.UpdatePopupAction)).
|
||||
Post("/delete", new(period.DeleteAction)).
|
||||
|
||||
// 用户流量包
|
||||
Prefix("/finance/packages/user-packages").
|
||||
Get("", new(userpackages.IndexAction)).
|
||||
GetPost("/createPopup", new(userpackages.CreatePopupAction)).
|
||||
Post("/price", new(userpackages.PriceAction)).
|
||||
Post("/delete", new(userpackages.DeleteAction)).
|
||||
|
||||
//
|
||||
EndAll()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package periods
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct{}) {
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
Count int32
|
||||
Unit string
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
var periodId int64
|
||||
|
||||
defer func() {
|
||||
this.CreateLogInfo(codes.TrafficPackagePeriod_LogCreateTrafficPackagePeriod, periodId)
|
||||
}()
|
||||
|
||||
if params.Count <= 0 {
|
||||
this.FailField("count", "请输入有效期数量")
|
||||
}
|
||||
|
||||
createResp, err := this.RPC().TrafficPackagePeriodRPC().CreateTrafficPackagePeriod(this.AdminContext(), &pb.CreateTrafficPackagePeriodRequest{
|
||||
Count: params.Count,
|
||||
Unit: params.Unit,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
periodId = createResp.TrafficPackagePeriodId
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package periods
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/finance/financeutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "period")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct{}) {
|
||||
// 是否已启用
|
||||
config, err := financeutils.ReadPriceConfig(this.AdminContext())
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
this.Data["enableTrafficPackages"] = config != nil && config.EnableTrafficPackages
|
||||
|
||||
// 所有有效期
|
||||
periodsResp, err := this.RPC().TrafficPackagePeriodRPC().FindAllTrafficPackagePeriods(this.AdminContext(), &pb.FindAllTrafficPackagePeriodsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var periodMaps = []maps.Map{}
|
||||
for _, period := range periodsResp.TrafficPackagePeriods {
|
||||
periodMaps = append(periodMaps, maps.Map{
|
||||
"id": period.Id,
|
||||
"count": period.Count,
|
||||
"unit": period.Unit,
|
||||
"unitName": userconfigs.TrafficPackagePeriodUnitName(period.Unit),
|
||||
"isOn": period.IsOn,
|
||||
})
|
||||
}
|
||||
this.Data["periods"] = periodMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package period
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
PeriodId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.TrafficPackagePeriod_LogDeleteTrafficPackagePeriod, params.PeriodId)
|
||||
|
||||
_, err := this.RPC().TrafficPackagePeriodRPC().DeleteTrafficPackagePeriod(this.AdminContext(), &pb.DeleteTrafficPackagePeriodRequest{TrafficPackagePeriodId: params.PeriodId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package period
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type UpdatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunGet(params struct {
|
||||
PeriodId int64
|
||||
}) {
|
||||
periodResp, err := this.RPC().TrafficPackagePeriodRPC().FindTrafficPackagePeriod(this.AdminContext(), &pb.FindTrafficPackagePeriodRequest{TrafficPackagePeriodId: params.PeriodId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var period = periodResp.TrafficPackagePeriod
|
||||
if period == nil {
|
||||
this.NotFound("trafficPackagePeriod", params.PeriodId)
|
||||
return
|
||||
}
|
||||
this.Data["period"] = maps.Map{
|
||||
"id": period.Id,
|
||||
"count": period.Count,
|
||||
"unitName": userconfigs.PricePeriodName(period.Unit),
|
||||
"isOn": period.IsOn,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
PeriodId int64
|
||||
IsOn bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.TrafficPackagePeriod_LogUpdateTrafficPackagePeriod, params.PeriodId)
|
||||
|
||||
_, err := this.RPC().TrafficPackagePeriodRPC().UpdateTrafficPackagePeriod(this.AdminContext(), &pb.UpdateTrafficPackagePeriodRequest{
|
||||
TrafficPackagePeriodId: params.PeriodId,
|
||||
IsOn: params.IsOn,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package packages
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type UpdatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunGet(params struct {
|
||||
PackageId int64
|
||||
}) {
|
||||
packageResp, err := this.RPC().TrafficPackageRPC().FindTrafficPackage(this.AdminContext(), &pb.FindTrafficPackageRequest{TrafficPackageId: params.PackageId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var p = packageResp.TrafficPackage
|
||||
if p == nil {
|
||||
this.NotFound("trafficPackage", params.PackageId)
|
||||
return
|
||||
}
|
||||
|
||||
this.Data["package"] = maps.Map{
|
||||
"id": p.Id,
|
||||
"size": p.Size,
|
||||
"unit": strings.ToUpper(p.Unit),
|
||||
"isOn": p.IsOn,
|
||||
}
|
||||
|
||||
this.Show()
|
||||
}
|
||||
|
||||
func (this *UpdatePopupAction) RunPost(params struct {
|
||||
PackageId int64
|
||||
IsOn bool
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.TrafficPackage_LogUpdateTrafficPackage, params.PackageId)
|
||||
|
||||
_, err := this.RPC().TrafficPackageRPC().UpdateTrafficPackage(this.AdminContext(), &pb.UpdateTrafficPackageRequest{
|
||||
TrafficPackageId: params.PackageId,
|
||||
IsOn: params.IsOn,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package packages
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type UpdatePriceAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePriceAction) RunPost(params struct {
|
||||
PackageId int64
|
||||
RegionId int64
|
||||
PeriodId int64
|
||||
Price float64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.TrafficPackagePrice_LogUpdateTrafficPackagePrice, params.PackageId, params.RegionId, params.PeriodId)
|
||||
|
||||
_, err := this.RPC().TrafficPackagePriceRPC().UpdateTrafficPackagePrice(this.AdminContext(), &pb.UpdateTrafficPackagePriceRequest{
|
||||
TrafficPackageId: params.PackageId,
|
||||
NodeRegionId: params.RegionId,
|
||||
TrafficPackagePeriodId: params.PeriodId,
|
||||
Price: params.Price,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package packages
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type UpdatePricesPopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *UpdatePricesPopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *UpdatePricesPopupAction) RunGet(params struct {
|
||||
PackageId int64
|
||||
}) {
|
||||
packageResp, err := this.RPC().TrafficPackageRPC().FindTrafficPackage(this.AdminContext(), &pb.FindTrafficPackageRequest{
|
||||
TrafficPackageId: params.PackageId,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var p = packageResp.TrafficPackage
|
||||
if p == nil {
|
||||
this.NotFound("trafficPackage", params.PackageId)
|
||||
return
|
||||
}
|
||||
this.Data["package"] = maps.Map{
|
||||
"id": p.Id,
|
||||
"size": p.Size,
|
||||
"unit": strings.ToUpper(p.Unit),
|
||||
}
|
||||
|
||||
// 所有区域
|
||||
regionsResp, err := this.RPC().NodeRegionRPC().FindAllAvailableNodeRegions(this.AdminContext(), &pb.FindAllAvailableNodeRegionsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var regionMaps = []maps.Map{}
|
||||
for _, region := range regionsResp.NodeRegions {
|
||||
regionMaps = append(regionMaps, maps.Map{
|
||||
"id": region.Id,
|
||||
"name": region.Name,
|
||||
})
|
||||
}
|
||||
this.Data["regions"] = regionMaps
|
||||
|
||||
// 有效期
|
||||
periodsResp, err := this.RPC().TrafficPackagePeriodRPC().FindAllAvailableTrafficPackagePeriods(this.AdminContext(), &pb.FindAllAvailableTrafficPackagePeriodsRequest{})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
var periodMaps = []maps.Map{}
|
||||
for _, period := range periodsResp.TrafficPackagePeriods {
|
||||
periodMaps = append(periodMaps, maps.Map{
|
||||
"id": period.Id,
|
||||
"name": types.String(period.Count) + userconfigs.TrafficPackagePeriodUnitName(period.Unit),
|
||||
})
|
||||
}
|
||||
this.Data["periods"] = periodMaps
|
||||
|
||||
// 所有价格
|
||||
pricesResp, err := this.RPC().TrafficPackagePriceRPC().FindTrafficPackagePrices(this.AdminContext(), &pb.FindTrafficPackagePricesRequest{TrafficPackageId: params.PackageId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var priceMap = map[string]float64{} // regionId@periodId => price
|
||||
for _, price := range pricesResp.TrafficPackagePrices {
|
||||
priceMap[types.String(price.NodeRegionId)+"@"+types.String(price.TrafficPackagePeriodId)] = price.Price
|
||||
}
|
||||
|
||||
this.Data["prices"] = priceMap
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package userpackages
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/actions"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
)
|
||||
|
||||
type CreatePopupAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) Init() {
|
||||
this.Nav("", "", "")
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunGet(params struct{}) {
|
||||
// 价格
|
||||
pricesResp, err := this.RPC().TrafficPackagePriceRPC().FindAllTrafficPackagePrices(this.AdminContext(), &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.AdminContext(), &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.AdminContext(), &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.AdminContext(), &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()
|
||||
}
|
||||
|
||||
func (this *CreatePopupAction) RunPost(params struct {
|
||||
UserId int64
|
||||
PackageId int64
|
||||
RegionId int64
|
||||
PeriodId int64
|
||||
Count int32
|
||||
|
||||
Must *actions.Must
|
||||
CSRF *actionutils.CSRF
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.UserTrafficPackage_LogCreateUserTrafficPackage, params.UserId, params.PackageId, params.RegionId, params.PeriodId, params.Count)
|
||||
|
||||
if params.UserId <= 0 {
|
||||
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
|
||||
}
|
||||
|
||||
resp, err := this.RPC().TrafficPackagePriceRPC().FindTrafficPackagePrice(this.AdminContext(), &pb.FindTrafficPackagePriceRequest{
|
||||
TrafficPackageId: params.PackageId,
|
||||
NodeRegionId: params.RegionId,
|
||||
TrafficPackagePeriodId: params.PeriodId,
|
||||
Count: params.Count,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
if resp.Price == 0 {
|
||||
this.Fail("当前所选条件下的流量包不可用")
|
||||
return
|
||||
}
|
||||
|
||||
_, err = this.RPC().UserTrafficPackageRPC().CreateUserTrafficPackage(this.AdminContext(), &pb.CreateUserTrafficPackageRequest{
|
||||
UserId: params.UserId,
|
||||
TrafficPackageId: params.PackageId,
|
||||
NodeRegionId: params.RegionId,
|
||||
TrafficPackagePeriodId: params.PeriodId,
|
||||
Count: params.Count,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package userpackages
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
type DeleteAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *DeleteAction) RunPost(params struct {
|
||||
UserPackageId int64
|
||||
}) {
|
||||
defer this.CreateLogInfo(codes.UserTrafficPackage_LogDeleteUserTrafficPackage, params.UserPackageId)
|
||||
|
||||
_, err := this.RPC().UserTrafficPackageRPC().DeleteUserTrafficPackage(this.AdminContext(), &pb.DeleteUserTrafficPackageRequest{UserTrafficPackageId: params.UserPackageId})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
this.Success()
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package userpackages
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/dateutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
)
|
||||
|
||||
type IndexAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *IndexAction) Init() {
|
||||
this.Nav("", "", "userPackage")
|
||||
}
|
||||
|
||||
func (this *IndexAction) RunGet(params struct {
|
||||
UserId int64
|
||||
RegionId int64
|
||||
PackageId int64
|
||||
PeriodId int64
|
||||
}) {
|
||||
countResp, err := this.RPC().UserTrafficPackageRPC().CountUserTrafficPackages(this.AdminContext(), &pb.CountUserTrafficPackagesRequest{
|
||||
TrafficPackageId: params.PackageId,
|
||||
NodeRegionId: params.RegionId,
|
||||
UserId: params.UserId,
|
||||
ExpiresDay: "",
|
||||
TrafficPackagePeriodId: params.PeriodId,
|
||||
})
|
||||
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.AdminContext(), &pb.ListUserTrafficPackagesRequest{
|
||||
TrafficPackageId: params.PackageId,
|
||||
UserId: params.UserId,
|
||||
NodeRegionId: params.RegionId,
|
||||
TrafficPackagePeriodId: params.PeriodId,
|
||||
ExpiresDay: "",
|
||||
AvailableOnly: false,
|
||||
Offset: page.Offset,
|
||||
Size: page.Size,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var userPackageMaps = []maps.Map{}
|
||||
for _, userPackage := range userPackagesResp.UserTrafficPackages {
|
||||
// user
|
||||
var userMap maps.Map
|
||||
if userPackage.User != nil {
|
||||
userMap = maps.Map{
|
||||
"id": userPackage.User.Id,
|
||||
"username": userPackage.User.Username,
|
||||
"fullname": userPackage.User.Fullname,
|
||||
}
|
||||
}
|
||||
|
||||
// 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),
|
||||
"user": userMap,
|
||||
"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),
|
||||
"canDelete": userPackage.CanDelete,
|
||||
"isExpired": userPackage.DayTo < timeutil.Format("Ymd"),
|
||||
"isUsedAll": userPackage.UsedBytes >= userPackage.TotalBytes,
|
||||
})
|
||||
}
|
||||
this.Data["userPackages"] = userPackageMaps
|
||||
|
||||
this.Show()
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package userpackages
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
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.AdminContext(), &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()
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
type OptionsAction struct {
|
||||
actionutils.ParentAction
|
||||
}
|
||||
|
||||
func (this *OptionsAction) RunPost(params struct {
|
||||
Keyword string
|
||||
}) {
|
||||
usersResp, err := this.RPC().UserRPC().ListEnabledUsers(this.AdminContext(), &pb.ListEnabledUsersRequest{
|
||||
Keyword: params.Keyword,
|
||||
Offset: 0,
|
||||
Size: 100,
|
||||
})
|
||||
if err != nil {
|
||||
this.ErrorPage(err)
|
||||
return
|
||||
}
|
||||
|
||||
var userMaps = []maps.Map{}
|
||||
for _, user := range usersResp.Users {
|
||||
userMaps = append(userMaps, maps.Map{
|
||||
"id": user.Id,
|
||||
"fullname": user.Fullname,
|
||||
"username": user.Username,
|
||||
"name": user.Fullname + "(" + user.Username + ")",
|
||||
})
|
||||
}
|
||||
this.Data["users"] = userMaps
|
||||
|
||||
this.Success()
|
||||
}
|
||||
Reference in New Issue
Block a user