支持购买套餐/续费套餐/用户账户操作等

This commit is contained in:
GoEdgeLab
2021-11-08 20:52:15 +08:00
parent 1f9e3e428b
commit dcfba222e2
24 changed files with 582 additions and 14 deletions

View File

@@ -0,0 +1,80 @@
package accounts
import (
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
)
type UserAccountDailyStatDAO dbs.DAO
func NewUserAccountDailyStatDAO() *UserAccountDailyStatDAO {
return dbs.NewDAO(&UserAccountDailyStatDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgeUserAccountDailyStats",
Model: new(UserAccountDailyStat),
PkName: "id",
},
}).(*UserAccountDailyStatDAO)
}
var SharedUserAccountDailyStatDAO *UserAccountDailyStatDAO
func init() {
dbs.OnReady(func() {
SharedUserAccountDailyStatDAO = NewUserAccountDailyStatDAO()
})
}
// UpdateDailyStat 更新当天统计数据
func (this *UserAccountDailyStatDAO) UpdateDailyStat(tx *dbs.Tx) error {
var day = timeutil.Format("Ymd")
var month = timeutil.Format("Ym")
income, err := SharedUserAccountLogDAO.SumDailyEventTypes(tx, day, userconfigs.AccountIncomeEventTypes)
if err != nil {
return err
}
expense, err := SharedUserAccountLogDAO.SumDailyEventTypes(tx, day, userconfigs.AccountExpenseEventTypes)
if err != nil {
return err
}
if expense < 0 {
expense = -expense
}
return this.Query(tx).
InsertOrUpdateQuickly(maps.Map{
"day": day,
"month": month,
"income": income,
"expense": expense,
}, maps.Map{
"income": income,
"expense": expense,
})
}
// FindDailyStats 查看按天统计
func (this *UserAccountDailyStatDAO) FindDailyStats(tx *dbs.Tx, dayFrom string, dayTo string) (result []*UserAccountDailyStat, err error) {
_, err = this.Query(tx).
Between("day", dayFrom, dayTo).
Slice(&result).
FindAll()
return
}
// FindMonthlyStats 查看某月统计
func (this *UserAccountDailyStatDAO) FindMonthlyStats(tx *dbs.Tx, dayFrom string, dayTo string) (result []*UserAccountDailyStat, err error) {
_, err = this.Query(tx).
Result("SUM(income) AS income", "SUM(expense) AS expense", "month").
Between("day", dayFrom, dayTo).
Group("month").
Slice(&result).
FindAll()
return
}

View File

@@ -0,0 +1,6 @@
package accounts
import (
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
)

View File

@@ -0,0 +1,22 @@
package accounts
// UserAccountDailyStat 账户每日统计
type UserAccountDailyStat struct {
Id uint32 `field:"id"` // ID
Day string `field:"day"` // YYYYMMDD
Month string `field:"month"` // YYYYMM
Income float64 `field:"income"` // 收入
Expense float64 `field:"expense"` // 支出
}
type UserAccountDailyStatOperator struct {
Id interface{} // ID
Day interface{} // YYYYMMDD
Month interface{} // YYYYMM
Income interface{} // 收入
Expense interface{} // 支出
}
func NewUserAccountDailyStatOperator() *UserAccountDailyStatOperator {
return &UserAccountDailyStatOperator{}
}

View File

@@ -0,0 +1 @@
package accounts

View File

@@ -0,0 +1,172 @@
package accounts
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
)
type UserAccountDAO dbs.DAO
func NewUserAccountDAO() *UserAccountDAO {
return dbs.NewDAO(&UserAccountDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgeUserAccounts",
Model: new(UserAccount),
PkName: "id",
},
}).(*UserAccountDAO)
}
var SharedUserAccountDAO *UserAccountDAO
func init() {
dbs.OnReady(func() {
SharedUserAccountDAO = NewUserAccountDAO()
})
}
// FindUserAccountWithUserId 根据用户ID查找用户账户
func (this *UserAccountDAO) FindUserAccountWithUserId(tx *dbs.Tx, userId int64) (*UserAccount, error) {
if userId <= 0 {
return nil, errors.New("invalid userId '" + types.String(userId) + "'")
}
// 用户是否存在
user, err := models.SharedUserDAO.FindEnabledUser(tx, userId, nil)
if err != nil {
return nil, err
}
if user == nil {
return nil, errors.New("invalid userId '" + types.String(userId) + "'")
}
account, err := this.Query(tx).
Attr("userId", userId).
Find()
if err != nil {
return nil, err
}
if account != nil {
return account.(*UserAccount), nil
}
var op = NewUserAccountOperator()
op.UserId = userId
_, err = this.SaveInt64(tx, op)
if err != nil {
return nil, err
}
return this.FindUserAccountWithUserId(tx, userId)
}
// FindUserAccountWithAccountId 根据ID查找用户账户
func (this *UserAccountDAO) FindUserAccountWithAccountId(tx *dbs.Tx, accountId int64) (*UserAccount, error) {
one, err := this.Query(tx).
Pk(accountId).
Find()
if one != nil {
return one.(*UserAccount), nil
}
return nil, err
}
// UpdateUserAccount 操作用户账户
func (this *UserAccountDAO) UpdateUserAccount(tx *dbs.Tx, accountId int64, delta float32, eventType userconfigs.AccountEventType, description string, params maps.Map) error {
account, err := this.FindUserAccountWithAccountId(tx, accountId)
if err != nil {
return err
}
if account == nil {
return errors.New("invalid account id '" + types.String(accountId) + "'")
}
var userId = int64(account.Id)
var deltaFloat64 = float64(delta)
if deltaFloat64 < 0 && account.Total < -deltaFloat64 {
return errors.New("not enough account quota to decrease")
}
// 操作账户
err = this.Query(tx).
Pk(account.Id).
Set("total", dbs.SQL("total+:delta")).
Param("delta", delta).
UpdateQuickly()
if err != nil {
return err
}
// 生成日志
err = SharedUserAccountLogDAO.CreateAccountLog(tx, userId, accountId, delta, 0, eventType, description, params)
if err != nil {
return err
}
return nil
}
// UpdateUserAccountFrozen 操作用户账户冻结余额
func (this *UserAccountDAO) UpdateUserAccountFrozen(tx *dbs.Tx, userId int64, delta float32, eventType userconfigs.AccountEventType, description string, params maps.Map) error {
account, err := this.FindUserAccountWithUserId(tx, userId)
if err != nil {
return err
}
var deltaFloat64 = float64(delta)
if deltaFloat64 < 0 && account.TotalFrozen < -deltaFloat64 {
return errors.New("not enough account frozen quota to decrease")
}
// 操作账户
err = this.Query(tx).
Pk(account.Id).
Set("totalFrozen", dbs.SQL("total+:delta")).
Param("delta", delta).
UpdateQuickly()
if err != nil {
return err
}
// 生成日志
err = SharedUserAccountLogDAO.CreateAccountLog(tx, userId, int64(account.Id), 0, delta, eventType, description, params)
if err != nil {
return err
}
return nil
}
// CountAllAccounts 计算所有账户数量
func (this *UserAccountDAO) CountAllAccounts(tx *dbs.Tx, keyword string) (int64, error) {
var query = this.Query(tx)
if len(keyword) > 0 {
query.Where("userId IN (SELECT id FROM " + models.SharedUserDAO.Table + " WHERE state=1 AND (username LIKE :keyword OR fullname LIKE :keyword))")
query.Param("keyword", keyword)
} else {
query.Where("userId IN (SELECT id FROM " + models.SharedUserDAO.Table + " WHERE state=1)")
}
return query.Count()
}
// ListAccounts 列出单页账户
func (this *UserAccountDAO) ListAccounts(tx *dbs.Tx, keyword string, offset int64, size int64) (result []*UserAccount, err error) {
var query = this.Query(tx)
if len(keyword) > 0 {
query.Where("userId IN (SELECT id FROM " + models.SharedUserDAO.Table + " WHERE state=1 AND (username LIKE :keyword OR fullname LIKE :keyword))")
query.Param("keyword", keyword)
} else {
query.Where("userId IN (SELECT id FROM " + models.SharedUserDAO.Table + " WHERE state=1)")
}
_, err = query.
DescPk().
Offset(offset).
Limit(size).
Slice(&result).
FindAll()
return
}

View File

@@ -0,0 +1,6 @@
package accounts
import (
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
)

View File

@@ -0,0 +1,128 @@
package accounts
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
timeutil "github.com/iwind/TeaGo/utils/time"
)
type UserAccountLogDAO dbs.DAO
func NewUserAccountLogDAO() *UserAccountLogDAO {
return dbs.NewDAO(&UserAccountLogDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgeUserAccountLogs",
Model: new(UserAccountLog),
PkName: "id",
},
}).(*UserAccountLogDAO)
}
var SharedUserAccountLogDAO *UserAccountLogDAO
func init() {
dbs.OnReady(func() {
SharedUserAccountLogDAO = NewUserAccountLogDAO()
})
}
// CreateAccountLog 生成用户账户日志
func (this *UserAccountLogDAO) CreateAccountLog(tx *dbs.Tx, userId int64, accountId int64, delta float32, deltaFrozen float32, eventType userconfigs.AccountEventType, description string, params maps.Map) error {
var op = NewUserAccountLogOperator()
op.UserId = userId
op.AccountId = accountId
op.Delta = delta
op.DeltaFrozen = deltaFrozen
account, err := SharedUserAccountDAO.FindUserAccountWithAccountId(tx, accountId)
if err != nil {
return err
}
if account == nil {
return errors.New("invalid account id '" + types.String(accountId) + "'")
}
op.Total = account.Total
op.TotalFrozen = account.TotalFrozen
op.EventType = eventType
op.Description = description
if params == nil {
params = maps.Map{}
}
op.Params = params.AsJSON()
op.Day = timeutil.Format("Ymd")
err = this.Save(tx, op)
if err != nil {
return err
}
return SharedUserAccountDailyStatDAO.UpdateDailyStat(tx)
}
// CountAccountLogs 计算日志数量
func (this *UserAccountLogDAO) CountAccountLogs(tx *dbs.Tx, userId int64, accountId int64, keyword string, eventType string) (int64, error) {
var query = this.Query(tx)
if userId > 0 {
query.Attr("userId", userId)
}
if accountId > 0 {
query.Attr("accountId", accountId)
}
if len(keyword) > 0 {
query.Where("(userId IN (SELECT id FROM " + models.SharedUserDAO.Table + " WHERE state=1 AND (username LIKE :keyword OR fullname LIKE :keyword)) OR description LIKE :keyword)")
query.Param("keyword", "%"+keyword+"%")
}
if len(eventType) > 0 {
query.Attr("eventType", eventType)
}
return query.Count()
}
// ListAccountLogs 列出单页日志
func (this *UserAccountLogDAO) ListAccountLogs(tx *dbs.Tx, userId int64, accountId int64, keyword string, eventType string, offset int64, size int64) (result []*UserAccountLog, err error) {
var query = this.Query(tx)
if userId > 0 {
query.Attr("userId", userId)
}
if accountId > 0 {
query.Attr("accountId", accountId)
}
if len(keyword) > 0 {
query.Where("(userId IN (SELECT id FROM " + models.SharedUserDAO.Table + " WHERE state=1 AND (username LIKE :keyword OR fullname LIKE :keyword)) OR description LIKE :keyword)")
query.Param("keyword", "%"+keyword+"%")
}
if len(eventType) > 0 {
query.Attr("eventType", eventType)
}
_, err = query.
DescPk().
Offset(offset).
Limit(size).
Slice(&result).
FindAll()
return
}
// SumDailyEventTypes 统计某天数据总和
func (this *UserAccountLogDAO) SumDailyEventTypes(tx *dbs.Tx, day string, eventTypes []userconfigs.AccountEventType) (float32, error) {
if len(eventTypes) == 0 {
return 0, nil
}
result, err := this.Query(tx).
Attr("day", day).
Attr("eventType", eventTypes).
Sum("delta", 0)
if err != nil {
return 0, err
}
return types.Float32(result), nil
}

View File

@@ -0,0 +1,6 @@
package accounts
import (
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
)

View File

@@ -0,0 +1,36 @@
package accounts
// UserAccountLog 用户账户日志
type UserAccountLog struct {
Id uint64 `field:"id"` // ID
UserId uint64 `field:"userId"` // 用户ID
AccountId uint64 `field:"accountId"` // 账户ID
Delta float64 `field:"delta"` // 操作余额的数量(可为负)
DeltaFrozen float64 `field:"deltaFrozen"` // 操作冻结的数量(可为负)
Total float64 `field:"total"` // 操作后余额
TotalFrozen float64 `field:"totalFrozen"` // 操作后冻结余额
EventType string `field:"eventType"` // 类型
Description string `field:"description"` // 描述文字
Day string `field:"day"` // YYYYMMDD
CreatedAt uint64 `field:"createdAt"` // 时间
Params string `field:"params"` // 参数
}
type UserAccountLogOperator struct {
Id interface{} // ID
UserId interface{} // 用户ID
AccountId interface{} // 账户ID
Delta interface{} // 操作余额的数量(可为负)
DeltaFrozen interface{} // 操作冻结的数量(可为负)
Total interface{} // 操作后余额
TotalFrozen interface{} // 操作后冻结余额
EventType interface{} // 类型
Description interface{} // 描述文字
Day interface{} // YYYYMMDD
CreatedAt interface{} // 时间
Params interface{} // 参数
}
func NewUserAccountLogOperator() *UserAccountLogOperator {
return &UserAccountLogOperator{}
}

View File

@@ -0,0 +1 @@
package accounts

View File

@@ -0,0 +1,20 @@
package accounts
// UserAccount 用户账号
type UserAccount struct {
Id uint64 `field:"id"` // ID
UserId uint64 `field:"userId"` // 用户ID
Total float64 `field:"total"` // 可用总余额
TotalFrozen float64 `field:"totalFrozen"` // 冻结余额
}
type UserAccountOperator struct {
Id interface{} // ID
UserId interface{} // 用户ID
Total interface{} // 可用总余额
TotalFrozen interface{} // 冻结余额
}
func NewUserAccountOperator() *UserAccountOperator {
return &UserAccountOperator{}
}

View File

@@ -0,0 +1 @@
package accounts

View File

@@ -5,6 +5,7 @@ import (
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea" "github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs" "github.com/iwind/TeaGo/dbs"
"strconv"
) )
const ( const (
@@ -85,7 +86,7 @@ func (this *ClientBrowserDAO) FindBrowserIdWithNameCacheable(tx *dbs.Tx, browser
browserId, err := this.Query(tx). browserId, err := this.Query(tx).
Where("JSON_CONTAINS(codes, :browserName)"). Where("JSON_CONTAINS(codes, :browserName)").
Param("browserName", "\""+browserName+"\""). // 查询的需要是个JSON字符串所以这里加双引号 Param("browserName", strconv.Quote(browserName)). // 查询的需要是个JSON字符串所以这里加双引号
ResultPk(). ResultPk().
FindInt64Col(0) FindInt64Col(0)
if err != nil { if err != nil {

View File

@@ -5,6 +5,7 @@ import (
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea" "github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs" "github.com/iwind/TeaGo/dbs"
"strconv"
) )
const ( const (
@@ -85,7 +86,7 @@ func (this *ClientSystemDAO) FindSystemIdWithNameCacheable(tx *dbs.Tx, systemNam
systemId, err := this.Query(tx). systemId, err := this.Query(tx).
Where("JSON_CONTAINS(codes, :systemName)"). Where("JSON_CONTAINS(codes, :systemName)").
Param("systemName", "\""+systemName+"\""). // 查询的需要是个JSON字符串所以这里加双引号 Param("systemName", strconv.Quote(systemName)). // 查询的需要是个JSON字符串所以这里加双引号
ResultPk(). ResultPk().
FindInt64Col(0) FindInt64Col(0)
if err != nil { if err != nil {

View File

@@ -7,6 +7,7 @@ import (
"github.com/iwind/TeaGo/Tea" "github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs" "github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/types" "github.com/iwind/TeaGo/types"
"strconv"
) )
const ( const (
@@ -119,7 +120,7 @@ func (this *RegionCityDAO) FindCityIdWithNameCacheable(tx *dbs.Tx, provinceId in
cityId, err := this.Query(tx). cityId, err := this.Query(tx).
Attr("provinceId", provinceId). Attr("provinceId", provinceId).
Where("JSON_CONTAINS(codes, :cityName)"). Where("JSON_CONTAINS(codes, :cityName)").
Param("cityName", "\""+cityName+"\""). // 查询的需要是个JSON字符串所以这里加双引号 Param("cityName", strconv.Quote(cityName)). // 查询的需要是个JSON字符串所以这里加双引号
ResultPk(). ResultPk().
FindInt64Col(0) FindInt64Col(0)
if err != nil { if err != nil {

View File

@@ -7,6 +7,7 @@ import (
"github.com/iwind/TeaGo/dbs" "github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/types" "github.com/iwind/TeaGo/types"
"github.com/mozillazg/go-pinyin" "github.com/mozillazg/go-pinyin"
"strconv"
"strings" "strings"
) )
@@ -88,7 +89,7 @@ func (this *RegionCountryDAO) FindCountryIdWithDataId(tx *dbs.Tx, dataId string)
func (this *RegionCountryDAO) FindCountryIdWithName(tx *dbs.Tx, countryName string) (int64, error) { func (this *RegionCountryDAO) FindCountryIdWithName(tx *dbs.Tx, countryName string) (int64, error) {
return this.Query(tx). return this.Query(tx).
Where("JSON_CONTAINS(codes, :countryName)"). Where("JSON_CONTAINS(codes, :countryName)").
Param("countryName", "\""+countryName+"\""). // 查询的需要是个JSON字符串所以这里加双引号 Param("countryName", strconv.Quote(countryName)). // 查询的需要是个JSON字符串所以这里加双引号
ResultPk(). ResultPk().
FindInt64Col(0) FindInt64Col(0)
} }

View File

@@ -5,6 +5,7 @@ import (
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea" "github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs" "github.com/iwind/TeaGo/dbs"
"strconv"
) )
const ( const (
@@ -85,7 +86,7 @@ func (this *RegionProviderDAO) FindProviderIdWithNameCacheable(tx *dbs.Tx, provi
providerId, err := this.Query(tx). providerId, err := this.Query(tx).
Where("JSON_CONTAINS(codes, :providerName)"). Where("JSON_CONTAINS(codes, :providerName)").
Param("providerName", "\""+providerName+"\""). // 查询的需要是个JSON字符串所以这里加双引号 Param("providerName", strconv.Quote(providerName)). // 查询的需要是个JSON字符串所以这里加双引号
ResultPk(). ResultPk().
FindInt64Col(0) FindInt64Col(0)
if err != nil { if err != nil {

View File

@@ -7,6 +7,7 @@ import (
"github.com/iwind/TeaGo/Tea" "github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs" "github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/types" "github.com/iwind/TeaGo/types"
"strconv"
) )
const ( const (
@@ -88,7 +89,7 @@ func (this *RegionProvinceDAO) FindProvinceIdWithName(tx *dbs.Tx, countryId int6
return this.Query(tx). return this.Query(tx).
Attr("countryId", countryId). Attr("countryId", countryId).
Where("JSON_CONTAINS(codes, :provinceName)"). Where("JSON_CONTAINS(codes, :provinceName)").
Param("provinceName", "\""+provinceName+"\""). // 查询的需要是个JSON字符串所以这里加双引号 Param("provinceName", strconv.Quote(provinceName)). // 查询的需要是个JSON字符串所以这里加双引号
ResultPk(). ResultPk().
FindInt64Col(0) FindInt64Col(0)
} }

View File

@@ -8,6 +8,7 @@ import (
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea" "github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs" "github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types" "github.com/iwind/TeaGo/types"
stringutil "github.com/iwind/TeaGo/utils/string" stringutil "github.com/iwind/TeaGo/utils/string"
timeutil "github.com/iwind/TeaGo/utils/time" timeutil "github.com/iwind/TeaGo/utils/time"
@@ -55,15 +56,27 @@ func (this *UserDAO) DisableUser(tx *dbs.Tx, id int64) (rowsAffected int64, err
Update() Update()
} }
// FindEnabledUser 查找启用中的条目 // FindEnabledUser 查找启用的用户
func (this *UserDAO) FindEnabledUser(tx *dbs.Tx, id int64) (*User, error) { func (this *UserDAO) FindEnabledUser(tx *dbs.Tx, userId int64, cacheMap maps.Map) (*User, error) {
if cacheMap == nil {
cacheMap = maps.Map{}
}
var cacheKey = this.Table + ":FindEnabledUser:" + types.String(userId)
cache, ok := cacheMap[cacheKey]
if ok {
return cache.(*User), nil
}
result, err := this.Query(tx). result, err := this.Query(tx).
Pk(id). Pk(userId).
Attr("state", UserStateEnabled). Attr("state", UserStateEnabled).
Find() Find()
if result == nil { if result == nil {
return nil, err return nil, err
} }
cacheMap[cacheKey] = result
return result.(*User), err return result.(*User), err
} }

View File

@@ -136,3 +136,14 @@ func (this *UserPlanDAO) UpdateUserPlan(tx *dbs.Tx, userPlanId int64, planId int
op.IsOn = isOn op.IsOn = isOn
return this.Save(tx, op) return this.Save(tx, op)
} }
// UpdateUserPlanDayTo 修改套餐日期
func (this *UserPlanDAO) UpdateUserPlanDayTo(tx *dbs.Tx, userPlanId int64, dayTo string) error {
if userPlanId <= 0 {
return errors.New("invalid userPlanId")
}
var op = NewUserPlanOperator()
op.Id = userPlanId
op.DayTo = dayTo
return this.Save(tx, op)
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services" "github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils" rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
) )
// NSDomainService 域名相关服务 // NSDomainService 域名相关服务
@@ -89,7 +90,7 @@ func (this *NSDomainService) FindEnabledNSDomain(ctx context.Context, req *pb.Fi
// 用户 // 用户
var pbUser *pb.User var pbUser *pb.User
if domain.UserId > 0 { if domain.UserId > 0 {
user, err := models.SharedUserDAO.FindEnabledUser(tx, int64(domain.UserId)) user, err := models.SharedUserDAO.FindEnabledUser(tx, int64(domain.UserId), nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -148,6 +149,7 @@ func (this *NSDomainService) ListEnabledNSDomains(ctx context.Context, req *pb.L
return nil, err return nil, err
} }
pbDomains := []*pb.NSDomain{} pbDomains := []*pb.NSDomain{}
var cacheMap = maps.Map{}
for _, domain := range domains { for _, domain := range domains {
// 集群 // 集群
cluster, err := models.SharedNSClusterDAO.FindEnabledNSCluster(tx, int64(domain.ClusterId)) cluster, err := models.SharedNSClusterDAO.FindEnabledNSCluster(tx, int64(domain.ClusterId))
@@ -161,7 +163,7 @@ func (this *NSDomainService) ListEnabledNSDomains(ctx context.Context, req *pb.L
// 用户 // 用户
var pbUser *pb.User var pbUser *pb.User
if domain.UserId > 0 { if domain.UserId > 0 {
user, err := models.SharedUserDAO.FindEnabledUser(tx, int64(domain.UserId)) user, err := models.SharedUserDAO.FindEnabledUser(tx, int64(domain.UserId), cacheMap)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -163,7 +163,7 @@ func (this *UserService) FindEnabledUser(ctx context.Context, req *pb.FindEnable
tx := this.NullTx() tx := this.NullTx()
user, err := models.SharedUserDAO.FindEnabledUser(tx, req.UserId) user, err := models.SharedUserDAO.FindEnabledUser(tx, req.UserId, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -2,13 +2,14 @@ package utils
import ( import (
"github.com/TeaOSLab/EdgeAPI/internal/errors" "github.com/TeaOSLab/EdgeAPI/internal/errors"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/types" "github.com/iwind/TeaGo/types"
timeutil "github.com/iwind/TeaGo/utils/time" timeutil "github.com/iwind/TeaGo/utils/time"
"regexp" "regexp"
"time" "time"
) )
// 计算日期之间的所有日期格式为YYYYMMDD // RangeDays 计算日期之间的所有日期格式为YYYYMMDD
func RangeDays(dayFrom string, dayTo string) ([]string, error) { func RangeDays(dayFrom string, dayTo string) ([]string, error) {
ok, err := regexp.MatchString(`^\d{8}$`, dayFrom) ok, err := regexp.MatchString(`^\d{8}$`, dayFrom)
if err != nil { if err != nil {
@@ -56,7 +57,56 @@ func RangeDays(dayFrom string, dayTo string) ([]string, error) {
return result, nil return result, nil
} }
// 计算小时之间的所有小时格式为YYYYMMDDHH // RangeMonths 计算日期之间的所有月份格式为YYYYMM
func RangeMonths(dayFrom string, dayTo string) ([]string, error) {
ok, err := regexp.MatchString(`^\d{8}$`, dayFrom)
if err != nil {
return nil, err
}
if !ok {
return nil, errors.New("invalid 'dayFrom'")
}
ok, err = regexp.MatchString(`^\d{8}$`, dayTo)
if err != nil {
return nil, err
}
if !ok {
return nil, errors.New("invalid 'dayTo'")
}
if dayFrom > dayTo {
dayFrom, dayTo = dayTo, dayFrom
}
result := []string{dayFrom[:6]}
year := types.Int(dayFrom[:4])
month := types.Int(dayFrom[4:6])
day := types.Int(dayFrom[6:])
t := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.Local)
for {
t = t.AddDate(0, 0, 20)
newDay := timeutil.Format("Ymd", t)
if newDay <= dayTo {
var monthString = newDay[:6]
if !lists.ContainsString(result, monthString) {
result = append(result, monthString)
}
} else {
break
}
}
var endMonth = dayTo[:6]
if !lists.ContainsString(result, endMonth) {
result = append(result, endMonth)
}
return result, nil
}
// RangeHours 计算小时之间的所有小时格式为YYYYMMDDHH
func RangeHours(hourFrom string, hourTo string) ([]string, error) { func RangeHours(hourFrom string, hourTo string) ([]string, error) {
ok, err := regexp.MatchString(`^\d{10}$`, hourFrom) ok, err := regexp.MatchString(`^\d{10}$`, hourFrom)
if err != nil { if err != nil {

View File

@@ -10,6 +10,13 @@ func TestRangeDays(t *testing.T) {
t.Log(days) t.Log(days)
} }
func TestRangeMonth(t *testing.T) {
days, err := RangeMonths("20200101", "20210115")
if err != nil {
t.Fatal(err)
}
t.Log(days)
}
func TestRangeHours(t *testing.T) { func TestRangeHours(t *testing.T) {
{ {