优化表结构,重构模型,重新实现基于白银网关的提取节点流程
This commit is contained in:
75
README.md
75
README.md
@@ -1,32 +1,85 @@
|
||||
## TODO
|
||||
|
||||
日志记录,使用任务来实现
|
||||
限制提取单次最大量
|
||||
|
||||
支付后事件,需要检测是否已完成操作
|
||||
支付后异步任务,到时间后需要尝试完成订单,如果无法完成再关闭
|
||||
|
||||
重新实现接口 proxy 注册与注销接口:
|
||||
- 注册时向 redis ports 可用池中加入端口
|
||||
- 注销时需要同时移除可用池与租约池中的端口(需要考虑具体实现,考虑正在使用的节点归还问题)
|
||||
|
||||
otel 检查接口性能
|
||||
|
||||
trade/create 性能问题,缩短事务时间,考虑其他方式实现可靠分布式事务
|
||||
|
||||
需要确认以下 ID.GenSerial 的分布式并发安全性
|
||||
|
||||
### 长期
|
||||
|
||||
模型字段修改,特定枚举字段使用自定义类型代替通用 int32
|
||||
分离 task 的客户端,支持多进程(prefork 必要!)
|
||||
|
||||
调整目录结构:
|
||||
|
||||
```
|
||||
- /core 核心概念
|
||||
- /util 工具函数
|
||||
|
||||
- /models 模型
|
||||
- /queries 数据库层
|
||||
- /clients 三方依赖的客户端实例
|
||||
|
||||
- /services 服务层
|
||||
- /auth 认证相关,特化服务
|
||||
|
||||
- /app 应用相关,初始化日志,环境变量等
|
||||
- /http 协议层,http 服务
|
||||
- /cmd 主函数
|
||||
|
||||
逐层向上依赖
|
||||
cmd 调用 app, http 的初始化函数
|
||||
http 调用 clients 的初始化函数
|
||||
```
|
||||
|
||||
考虑一个方案限制接口请求速率,无侵入更好
|
||||
|
||||
冷数据迁移方案
|
||||
|
||||
proxy 网关更新接口可以传输更结构化的数据,直接区分不同类型以加快更新速度
|
||||
|
||||
## 业务逻辑
|
||||
|
||||
### 订单关闭的几种方式
|
||||
|
||||
1. 创建订单后推送异步任务,到时间后尝试关闭订单
|
||||
1. 创建订单后推送异步任务,到时间后尝试完成订单或关闭订单
|
||||
2. sse 接口推送订单状态,轮询尝试完成订单
|
||||
3. 异步回调事件,收到支付成功事件后自动完成订单
|
||||
4. 用户退出支付界面,客户端主动发起关闭订单
|
||||
|
||||
### 产品字典表
|
||||
|
||||
| 代码 | 产品 |
|
||||
|-------|------|
|
||||
| short | 短效代理 |
|
||||
| long | 长效代理 |
|
||||
| 代码 | 产品 |
|
||||
| ----- | ------------ |
|
||||
| short | 短效动态代理 |
|
||||
| long | 长效动态代理 |
|
||||
|
||||
## 问题备忘录
|
||||
### 节点分配与存储逻辑
|
||||
|
||||
### 商福通支付接口的同步跳转参数
|
||||
添加:
|
||||
- 检查用户 ip 是否在白名单内
|
||||
- 取用端口,不够则返回失败
|
||||
- 将分配结果转写成配置发送到网关
|
||||
- 保存通道信息和分配记录,其中通道信息以网关为主体,分配记录以用户为主体
|
||||
- 添加异步任务,当时间结束后释放取用的端口并清空网关配置
|
||||
|
||||
部分通道支持这个参数,银盛和汇付不支持这个参数
|
||||
删除:
|
||||
- 如果传入用户信息,检查要删除的连接是否属于该用户
|
||||
- 释放可用端口
|
||||
- redis 脚本中检查,如果端口所属节点已下线则直接忽略
|
||||
- 提交清空配置到网关
|
||||
|
||||
缩扩容:
|
||||
- 通过调度任务实现缩扩容
|
||||
- 每 n 秒检查一次全部配置,按代理分组
|
||||
- 获取所有代理后备配置
|
||||
- 后备配置/当前配置
|
||||
- 当比例 < 1.5 或 > 3 时,重新更新为 2 倍
|
||||
|
||||
172
cmd/gen/main.go
172
cmd/gen/main.go
@@ -1,11 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
m "platform/web/models"
|
||||
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gen"
|
||||
"gorm.io/gen/field"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/schema"
|
||||
)
|
||||
@@ -26,149 +25,42 @@ func main() {
|
||||
|
||||
g = gen.NewGenerator(gen.Config{
|
||||
OutPath: "web/queries",
|
||||
ModelPkgPath: "models",
|
||||
FieldNullable: true,
|
||||
FieldSignable: true,
|
||||
FieldWithTypeTag: true,
|
||||
Mode: gen.WithDefaultQuery | gen.WithoutContext,
|
||||
})
|
||||
g.UseDB(db)
|
||||
|
||||
// 公共参数
|
||||
common := []gen.ModelOpt{
|
||||
gen.FieldModify(func(field gen.Field) gen.Field {
|
||||
switch {
|
||||
case field.Type == "*time.Time":
|
||||
field.Type = "*orm.LocalDateTime"
|
||||
case field.Type == "time.Time":
|
||||
field.Type = "orm.LocalDateTime"
|
||||
case strings.Contains(field.Tags(), "numeric"):
|
||||
field.Type = "decimal.Decimal"
|
||||
}
|
||||
return field
|
||||
}),
|
||||
gen.FieldRename("contact_qq", "ContactQQ"),
|
||||
gen.FieldRename("ua", "UA"),
|
||||
}
|
||||
|
||||
// 生成模型
|
||||
customs := make(map[string]any)
|
||||
|
||||
// resource
|
||||
resourceShort := g.GenerateModel("resource_short", common...)
|
||||
customs["resource_short"] = resourceShort
|
||||
|
||||
resourceLong := g.GenerateModel("resource_long", common...)
|
||||
customs["resource_long"] = resourceLong
|
||||
|
||||
resource := g.GenerateModel("resource", append(common,
|
||||
gen.FieldRelate(field.HasOne, "Short", resourceShort, &field.RelateConfig{
|
||||
RelatePointer: true,
|
||||
GORMTag: field.GormTag{
|
||||
"foreignKey": []string{"ResourceID"},
|
||||
"references": []string{"ID"},
|
||||
},
|
||||
}),
|
||||
gen.FieldRelate(field.HasOne, "Long", resourceLong, &field.RelateConfig{
|
||||
RelatePointer: true,
|
||||
GORMTag: field.GormTag{
|
||||
"foreignKey": []string{"ResourceID"},
|
||||
"references": []string{"ID"},
|
||||
},
|
||||
}),
|
||||
)...)
|
||||
customs["resource"] = resource
|
||||
|
||||
// trade
|
||||
trade := g.GenerateModel("trade", common...)
|
||||
customs["trade"] = trade
|
||||
|
||||
refund := g.GenerateModel("refund", common...)
|
||||
customs["refund"] = refund
|
||||
|
||||
bill := g.GenerateModel("bill", append(common,
|
||||
gen.FieldRelate(field.BelongsTo, "Trade", trade, &field.RelateConfig{
|
||||
RelatePointer: true,
|
||||
GORMTag: field.GormTag{
|
||||
"foreignKey": []string{"TradeID"},
|
||||
},
|
||||
}),
|
||||
gen.FieldRelate(field.BelongsTo, "Refund", refund, &field.RelateConfig{
|
||||
RelatePointer: true,
|
||||
GORMTag: field.GormTag{
|
||||
"foreignKey": []string{"RefundID"},
|
||||
},
|
||||
}),
|
||||
gen.FieldRelate(field.BelongsTo, "Resource", resource, &field.RelateConfig{
|
||||
RelatePointer: true,
|
||||
GORMTag: field.GormTag{
|
||||
"foreignKey": []string{"ResourceID"},
|
||||
},
|
||||
}),
|
||||
)...)
|
||||
customs["bill"] = bill
|
||||
|
||||
// proxy
|
||||
edge := g.GenerateModel("edge", common...)
|
||||
customs["edge"] = edge
|
||||
|
||||
proxy := g.GenerateModel("proxy", append(common,
|
||||
gen.FieldRelate(field.HasMany, "Edges", edge, &field.RelateConfig{
|
||||
GORMTag: field.GormTag{
|
||||
"foreignKey": []string{"ProxyID"},
|
||||
"references": []string{"ID"},
|
||||
},
|
||||
}),
|
||||
)...)
|
||||
customs["proxy"] = proxy
|
||||
|
||||
// session
|
||||
user := g.GenerateModel("user", common...)
|
||||
customs["user"] = user
|
||||
|
||||
admin := g.GenerateModel("admin", common...)
|
||||
customs["admin"] = admin
|
||||
|
||||
client := g.GenerateModel("client", common...)
|
||||
customs["client"] = client
|
||||
|
||||
session := g.GenerateModel("session", append(common,
|
||||
gen.FieldRelate(field.BelongsTo, "User", user, &field.RelateConfig{
|
||||
RelatePointer: true,
|
||||
GORMTag: field.GormTag{
|
||||
"foreignKey": []string{"UserID"},
|
||||
},
|
||||
}),
|
||||
gen.FieldRelate(field.BelongsTo, "Admin", admin, &field.RelateConfig{
|
||||
RelatePointer: true,
|
||||
GORMTag: field.GormTag{
|
||||
"foreignKey": []string{"AdminID"},
|
||||
},
|
||||
}),
|
||||
gen.FieldRelate(field.BelongsTo, "Client", client, &field.RelateConfig{
|
||||
RelatePointer: true,
|
||||
GORMTag: field.GormTag{
|
||||
"foreignKey": []string{"ClientID"},
|
||||
"belongsTo": []string{"ID"},
|
||||
},
|
||||
}),
|
||||
)...)
|
||||
customs["session"] = session
|
||||
|
||||
// 生成表结构
|
||||
tables, _ := db.Migrator().GetTables()
|
||||
models := make([]any, len(tables))
|
||||
for i, name := range tables {
|
||||
if customs[name] != nil {
|
||||
models[i] = customs[name]
|
||||
} else {
|
||||
models[i] = g.GenerateModel(name, common...)
|
||||
}
|
||||
}
|
||||
|
||||
g.ApplyBasic(models...)
|
||||
|
||||
// 生成查询
|
||||
|
||||
g.ApplyBasic(
|
||||
m.Admin{},
|
||||
m.AdminRole{},
|
||||
m.Announcement{},
|
||||
m.Bill{},
|
||||
m.Channel{},
|
||||
m.Client{},
|
||||
m.Coupon{},
|
||||
m.Edge{},
|
||||
m.LinkAdminRole{},
|
||||
m.LinkAdminRolePermission{},
|
||||
m.LinkClientPermission{},
|
||||
m.LinkUserRole{},
|
||||
m.LinkUserRolePermission{},
|
||||
m.LogsLogin{},
|
||||
m.LogsRequest{},
|
||||
m.LogsUserBandwidth{},
|
||||
m.LogsUserUsage{},
|
||||
m.Permission{},
|
||||
m.Product{},
|
||||
m.Proxy{},
|
||||
m.Refund{},
|
||||
m.Resource{},
|
||||
m.ResourceLong{},
|
||||
m.ResourceShort{},
|
||||
m.Session{},
|
||||
m.Trade{},
|
||||
m.User{},
|
||||
m.UserRole{},
|
||||
m.Whitelist{},
|
||||
)
|
||||
g.Execute()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: server-dev
|
||||
name: lanhu
|
||||
|
||||
services:
|
||||
postgres:
|
||||
@@ -11,6 +11,7 @@ services:
|
||||
- "${DB_PORT}:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
- ./scripts/sql/init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||
restart: unless-stopped
|
||||
|
||||
redis:
|
||||
|
||||
86
pkg/u/u.go
86
pkg/u/u.go
@@ -5,11 +5,36 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// P 是一个工具函数,用于在表达式内原地创建一个指针
|
||||
// ====================
|
||||
// 逻辑
|
||||
// ====================
|
||||
|
||||
func Else[T any](v *T, or T) T {
|
||||
if v == nil {
|
||||
return or
|
||||
} else {
|
||||
return *v
|
||||
}
|
||||
}
|
||||
|
||||
func ElseTo[A any, B any](a *A, f func(A) B) *B {
|
||||
if a == nil {
|
||||
return nil
|
||||
} else {
|
||||
return P(f(*a))
|
||||
}
|
||||
}
|
||||
|
||||
// ====================
|
||||
// 指针
|
||||
// ====================
|
||||
|
||||
// P 原地创建值的指针
|
||||
func P[T any](v T) *T {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Z 转换值为不可空,如果值为 nil,则返回其零值
|
||||
func Z[T any](v *T) T {
|
||||
if v == nil {
|
||||
var zero T
|
||||
@@ -18,6 +43,7 @@ func Z[T any](v *T) T {
|
||||
return *v
|
||||
}
|
||||
|
||||
// X 转换值为可空,如果值为零值,则返回 nil
|
||||
func X[T comparable](v T) *T {
|
||||
var zero T
|
||||
if v == zero {
|
||||
@@ -26,28 +52,50 @@ func X[T comparable](v T) *T {
|
||||
return &v
|
||||
}
|
||||
|
||||
func Today() time.Time {
|
||||
var now = time.Now()
|
||||
return time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
||||
}
|
||||
// ====================
|
||||
// 数组
|
||||
// ====================
|
||||
|
||||
func Date(date time.Time) time.Time {
|
||||
return time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, date.Location())
|
||||
}
|
||||
|
||||
func SameDate(date time.Time) bool {
|
||||
var now = time.Now()
|
||||
return date.Year() == now.Year() && date.Month() == now.Month() && date.Day() == now.Day()
|
||||
}
|
||||
|
||||
func Or[T any](v *T, or T) T {
|
||||
if v == nil {
|
||||
return or
|
||||
} else {
|
||||
return *v
|
||||
func Map[T any, R any](src []T, convert func(T) R) []R {
|
||||
dst := make([]R, len(src))
|
||||
for i, item := range src {
|
||||
dst[i] = convert(item)
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// ====================
|
||||
// 时间
|
||||
// ====================
|
||||
|
||||
func DateHead(date time.Time) time.Time {
|
||||
var y, m, d = date.Date()
|
||||
return time.Date(y, m, d, 0, 0, 0, 0, date.Location())
|
||||
}
|
||||
|
||||
func DateFoot(date time.Time) time.Time {
|
||||
var y, m, d = date.Date()
|
||||
return time.Date(y, m, d, 23, 59, 59, 999999999, date.Location())
|
||||
}
|
||||
|
||||
func Today() time.Time {
|
||||
return DateHead(time.Now())
|
||||
}
|
||||
|
||||
func IsSameDate(date1, date2 time.Time) bool {
|
||||
var y1, m1, d1 = date1.Date()
|
||||
var y2, m2, d2 = date2.Date()
|
||||
return y1 == y2 && m1 == m2 && d1 == d2
|
||||
}
|
||||
|
||||
func IsToday(date time.Time) bool {
|
||||
return IsSameDate(date, time.Now())
|
||||
}
|
||||
|
||||
// ====================
|
||||
// 错误
|
||||
// ====================
|
||||
|
||||
func CombineErrors(errs []error) error {
|
||||
var combinedErr error = nil
|
||||
for _, err := range errs {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,6 @@ import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"platform/web/core"
|
||||
client2 "platform/web/domains/client"
|
||||
m "platform/web/models"
|
||||
q "platform/web/queries"
|
||||
s "platform/web/services"
|
||||
@@ -86,8 +85,8 @@ func authBearer(_ context.Context, token string) (*AuthCtx, error) {
|
||||
}
|
||||
|
||||
scopes := []string{}
|
||||
if session.Scopes_ != nil {
|
||||
scopes = strings.Split(*session.Scopes_, " ")
|
||||
if session.Scopes != nil {
|
||||
scopes = strings.Split(*session.Scopes, " ")
|
||||
}
|
||||
return &AuthCtx{
|
||||
User: session.User,
|
||||
@@ -138,8 +137,7 @@ func authClient(clientId, clientSecret string) (*m.Client, error) {
|
||||
}
|
||||
|
||||
// 检查客户端密钥
|
||||
spec := client2.Spec(client.Spec)
|
||||
if spec == client2.SpecWeb || spec == client2.SpecApi {
|
||||
if client.Spec == m.ClientSpecWeb || client.Spec == m.ClientSpecAPI {
|
||||
if bcrypt.CompareHashAndPassword([]byte(client.ClientSecret), []byte(clientSecret)) != nil {
|
||||
return nil, errors.New("客户端密钥错误")
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"platform/pkg/env"
|
||||
"platform/pkg/u"
|
||||
"platform/web/core"
|
||||
user2 "platform/web/domains/user"
|
||||
g "platform/web/globals"
|
||||
"platform/web/globals/orm"
|
||||
m "platform/web/models"
|
||||
@@ -162,7 +161,7 @@ func Token(c *fiber.Ctx) error {
|
||||
AccessToken: session.AccessToken,
|
||||
RefreshToken: u.Z(session.RefreshToken),
|
||||
ExpiresIn: int(time.Time(session.AccessTokenExpires).Sub(now).Seconds()),
|
||||
Scope: u.Z(session.Scopes_),
|
||||
Scope: u.Z(session.Scopes),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -202,7 +201,7 @@ func authAuthorizationCode(ctx *fiber.Ctx, auth *AuthCtx, req *TokenReq, now tim
|
||||
|
||||
user, err := q.User.Where(
|
||||
q.User.ID.Eq(codeCtx.UserID),
|
||||
q.User.Status.Eq(int32(user2.StatusEnabled)),
|
||||
q.User.Status.Eq(int(m.UserStatusEnabled)),
|
||||
).First()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -211,18 +210,20 @@ func authAuthorizationCode(ctx *fiber.Ctx, auth *AuthCtx, req *TokenReq, now tim
|
||||
// todo 检查 scope
|
||||
|
||||
// 生成会话
|
||||
ip, _ := orm.ParseInet(ctx.Get(core.HeaderUserIP))
|
||||
ua := ctx.Get(core.HeaderUserUA)
|
||||
session := &m.Session{
|
||||
IP: u.X(ctx.IP()),
|
||||
UA: u.X(ctx.Get(fiber.HeaderUserAgent)),
|
||||
IP: ip,
|
||||
UA: u.X(ua),
|
||||
UserID: &user.ID,
|
||||
ClientID: &auth.Client.ID,
|
||||
Scopes_: u.P(strings.Join(codeCtx.Scopes, " ")),
|
||||
Scopes: u.P(strings.Join(codeCtx.Scopes, " ")),
|
||||
AccessToken: uuid.NewString(),
|
||||
AccessTokenExpires: orm.LocalDateTime(now.Add(time.Duration(env.SessionAccessExpire) * time.Second)),
|
||||
AccessTokenExpires: now.Add(time.Duration(env.SessionAccessExpire) * time.Second),
|
||||
}
|
||||
if codeCtx.Remember {
|
||||
session.RefreshToken = u.P(uuid.NewString())
|
||||
session.RefreshTokenExpires = u.P(orm.LocalDateTime(now.Add(time.Duration(env.SessionRefreshExpire) * time.Second)))
|
||||
session.RefreshTokenExpires = u.P(now.Add(time.Duration(env.SessionRefreshExpire) * time.Second))
|
||||
}
|
||||
|
||||
err = SaveSession(session)
|
||||
@@ -237,12 +238,14 @@ func authClientCredential(ctx *fiber.Ctx, auth *AuthCtx, _ *TokenReq, now time.T
|
||||
// todo 检查 scope
|
||||
|
||||
// 生成会话
|
||||
ip, _ := orm.ParseInet(ctx.Get(core.HeaderUserIP))
|
||||
ua := ctx.Get(core.HeaderUserUA)
|
||||
session := &m.Session{
|
||||
IP: u.X(ctx.IP()),
|
||||
UA: u.X(ctx.Get(fiber.HeaderUserAgent)),
|
||||
IP: ip,
|
||||
UA: u.X(ua),
|
||||
ClientID: &auth.Client.ID,
|
||||
AccessToken: uuid.NewString(),
|
||||
AccessTokenExpires: orm.LocalDateTime(now.Add(time.Duration(env.SessionAccessExpire) * time.Second)),
|
||||
AccessTokenExpires: now.Add(time.Duration(env.SessionAccessExpire) * time.Second),
|
||||
}
|
||||
|
||||
// 保存会话
|
||||
@@ -255,6 +258,9 @@ func authClientCredential(ctx *fiber.Ctx, auth *AuthCtx, _ *TokenReq, now time.T
|
||||
}
|
||||
|
||||
func authPassword(ctx *fiber.Ctx, auth *AuthCtx, req *TokenReq, now time.Time) (*m.Session, error) {
|
||||
ip, _ := orm.ParseInet(ctx.Get(core.HeaderUserIP))
|
||||
ua := ctx.Get(core.HeaderUserUA)
|
||||
|
||||
var user *m.User
|
||||
err := q.Q.Transaction(func(tx *q.Query) (err error) {
|
||||
switch req.LoginType {
|
||||
@@ -267,7 +273,7 @@ func authPassword(ctx *fiber.Ctx, auth *AuthCtx, req *TokenReq, now time.Time) (
|
||||
user = &m.User{
|
||||
Phone: req.Username,
|
||||
Username: u.P(req.Username),
|
||||
Status: int32(user2.StatusEnabled),
|
||||
Status: m.UserStatusEnabled,
|
||||
}
|
||||
}
|
||||
case GrantPasswordEmail:
|
||||
@@ -285,15 +291,15 @@ func authPassword(ctx *fiber.Ctx, auth *AuthCtx, req *TokenReq, now time.Time) (
|
||||
}
|
||||
|
||||
// 账户状态
|
||||
if user2.Status(user.Status) == user2.StatusDisabled {
|
||||
if user.Status == m.UserStatusDisabled {
|
||||
slog.Debug("账户状态异常", "username", req.Username, "status", user.Status)
|
||||
return core.NewBizErr("账号无法登录")
|
||||
}
|
||||
|
||||
// 更新用户的登录时间
|
||||
user.LastLogin = u.P(orm.LocalDateTime(time.Now()))
|
||||
user.LastLoginHost = u.X(ctx.IP())
|
||||
user.LastLoginAgent = u.X(ctx.Get(fiber.HeaderUserAgent))
|
||||
user.LastLogin = u.P(time.Now())
|
||||
user.LastLoginIP = ip
|
||||
user.LastLoginUA = u.X(ua)
|
||||
if err := tx.User.Save(user); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -306,17 +312,17 @@ func authPassword(ctx *fiber.Ctx, auth *AuthCtx, req *TokenReq, now time.Time) (
|
||||
|
||||
// 生成会话
|
||||
session := &m.Session{
|
||||
IP: u.X(ctx.IP()),
|
||||
UA: u.X(ctx.Get(fiber.HeaderUserAgent)),
|
||||
IP: ip,
|
||||
UA: u.X(ua),
|
||||
UserID: &user.ID,
|
||||
ClientID: &auth.Client.ID,
|
||||
Scopes_: u.X(req.Scope),
|
||||
Scopes: u.X(req.Scope),
|
||||
AccessToken: uuid.NewString(),
|
||||
AccessTokenExpires: orm.LocalDateTime(now.Add(time.Duration(env.SessionAccessExpire) * time.Second)),
|
||||
AccessTokenExpires: now.Add(time.Duration(env.SessionAccessExpire) * time.Second),
|
||||
}
|
||||
if req.Remember {
|
||||
session.RefreshToken = u.P(uuid.NewString())
|
||||
session.RefreshTokenExpires = u.P(orm.LocalDateTime(now.Add(time.Duration(env.SessionRefreshExpire) * time.Second)))
|
||||
session.RefreshTokenExpires = u.P(now.Add(time.Duration(env.SessionRefreshExpire) * time.Second))
|
||||
}
|
||||
|
||||
err = SaveSession(session)
|
||||
@@ -340,10 +346,10 @@ func authRefreshToken(_ *fiber.Ctx, _ *AuthCtx, req *TokenReq, now time.Time) (*
|
||||
|
||||
// 生成令牌
|
||||
session.AccessToken = uuid.NewString()
|
||||
session.AccessTokenExpires = orm.LocalDateTime(now.Add(time.Duration(env.SessionAccessExpire) * time.Second))
|
||||
session.AccessTokenExpires = now.Add(time.Duration(env.SessionAccessExpire) * time.Second)
|
||||
if session.RefreshToken != nil {
|
||||
session.RefreshToken = u.P(uuid.NewString())
|
||||
session.RefreshTokenExpires = u.P(orm.LocalDateTime(now.Add(time.Duration(env.SessionRefreshExpire) * time.Second)))
|
||||
session.RefreshTokenExpires = u.P(now.Add(time.Duration(env.SessionRefreshExpire) * time.Second))
|
||||
}
|
||||
|
||||
// 保存令牌
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"platform/web/domains/client"
|
||||
m "platform/web/models"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
@@ -40,8 +39,7 @@ func (a *AuthCtx) PermitSecretClient(scopes ...string) (*AuthCtx, error) {
|
||||
if a.Client == nil {
|
||||
return a, ErrAuthenticateForbidden
|
||||
}
|
||||
spec := client.Spec(a.Client.Spec)
|
||||
if spec != client.SpecApi && spec != client.SpecWeb {
|
||||
if a.Client.Spec != m.ClientSpecAPI && a.Client.Spec != m.ClientSpecWeb {
|
||||
return a, ErrAuthenticateForbidden
|
||||
}
|
||||
if !a.checkScopes(scopes...) {
|
||||
@@ -50,16 +48,14 @@ func (a *AuthCtx) PermitSecretClient(scopes ...string) (*AuthCtx, error) {
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func (a *AuthCtx) PermitInternalClient(scopes ...string) (*AuthCtx, error) {
|
||||
func (a *AuthCtx) PermitOfficialClient(scopes ...string) (*AuthCtx, error) {
|
||||
if a.Client == nil {
|
||||
return a, ErrAuthenticateForbidden
|
||||
}
|
||||
spec := client.Spec(a.Client.Spec)
|
||||
if spec != client.SpecApi && spec != client.SpecWeb {
|
||||
if a.Client.Spec != m.ClientSpecAPI && a.Client.Spec != m.ClientSpecWeb {
|
||||
return a, ErrAuthenticateForbidden
|
||||
}
|
||||
cType := client.Type(a.Client.Type)
|
||||
if cType != client.TypeInternal {
|
||||
if a.Client.Type != m.ClientTypeOfficial {
|
||||
return a, ErrAuthenticateForbidden
|
||||
}
|
||||
if !a.checkScopes(scopes...) {
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
g "platform/web/globals"
|
||||
"platform/web/globals/orm"
|
||||
m "platform/web/models"
|
||||
q "platform/web/queries"
|
||||
"time"
|
||||
@@ -17,7 +16,7 @@ func FindSession(accessToken string, now time.Time) (*m.Session, error) {
|
||||
Preload(field.Associations).
|
||||
Where(
|
||||
q.Session.AccessToken.Eq(accessToken),
|
||||
q.Session.AccessTokenExpires.Gt(orm.LocalDateTime(now)),
|
||||
q.Session.AccessTokenExpires.Gt(now),
|
||||
).First()
|
||||
}
|
||||
|
||||
@@ -26,7 +25,7 @@ func FindSessionByRefresh(refreshToken string, now time.Time) (*m.Session, error
|
||||
Preload(field.Associations).
|
||||
Where(
|
||||
q.Session.RefreshToken.Eq(refreshToken),
|
||||
q.Session.RefreshTokenExpires.Gt(orm.LocalDateTime(now)),
|
||||
q.Session.RefreshTokenExpires.Gt(now),
|
||||
).First()
|
||||
}
|
||||
|
||||
|
||||
@@ -6,49 +6,6 @@ import (
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// region page
|
||||
|
||||
type PageReq struct {
|
||||
RawPage int `json:"page"`
|
||||
RawSize int `json:"size"`
|
||||
}
|
||||
|
||||
func (p *PageReq) GetPage() int {
|
||||
if p.RawPage < 1 {
|
||||
return 1
|
||||
}
|
||||
return p.RawPage
|
||||
}
|
||||
|
||||
func (p *PageReq) GetSize() int {
|
||||
if p.RawSize < 1 {
|
||||
return 10
|
||||
}
|
||||
if p.RawSize > 100 {
|
||||
return 100
|
||||
}
|
||||
return p.RawSize
|
||||
}
|
||||
|
||||
func (p *PageReq) GetOffset() int {
|
||||
return (p.GetPage() - 1) * p.GetSize()
|
||||
}
|
||||
|
||||
func (p *PageReq) GetLimit() int {
|
||||
return p.GetSize()
|
||||
}
|
||||
|
||||
type PageResp struct {
|
||||
Total int `json:"total"`
|
||||
Page int `json:"page"`
|
||||
Size int `json:"size"`
|
||||
List any `json:"list"`
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region error
|
||||
|
||||
type Err struct {
|
||||
msg string
|
||||
err error
|
||||
@@ -109,5 +66,3 @@ type ServErr struct{ Err }
|
||||
func NewServErr(msg string, err ...error) *ServErr {
|
||||
return &ServErr{newErr(msg, err...)}
|
||||
}
|
||||
|
||||
// endregion
|
||||
43
web/core/http.go
Normal file
43
web/core/http.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package core
|
||||
|
||||
const HeaderUserIP = "X-Data-IP"
|
||||
const HeaderUserUA = "X-Data-UA"
|
||||
|
||||
// PageReq 分页请求参数
|
||||
type PageReq struct {
|
||||
RawPage int `json:"page"`
|
||||
RawSize int `json:"size"`
|
||||
}
|
||||
|
||||
func (p *PageReq) GetPage() int {
|
||||
if p.RawPage < 1 {
|
||||
return 1
|
||||
}
|
||||
return p.RawPage
|
||||
}
|
||||
|
||||
func (p *PageReq) GetSize() int {
|
||||
if p.RawSize < 1 {
|
||||
return 10
|
||||
}
|
||||
if p.RawSize > 100 {
|
||||
return 100
|
||||
}
|
||||
return p.RawSize
|
||||
}
|
||||
|
||||
func (p *PageReq) GetOffset() int {
|
||||
return (p.GetPage() - 1) * p.GetSize()
|
||||
}
|
||||
|
||||
func (p *PageReq) GetLimit() int {
|
||||
return p.GetSize()
|
||||
}
|
||||
|
||||
// PageResp 分页响应参数
|
||||
type PageResp struct {
|
||||
Total int `json:"total"`
|
||||
Page int `json:"page"`
|
||||
Size int `json:"size"`
|
||||
List any `json:"list"`
|
||||
}
|
||||
29
web/core/model.go
Normal file
29
web/core/model.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"platform/pkg/u"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type IModel interface {
|
||||
GetID() int32
|
||||
}
|
||||
|
||||
type Model struct {
|
||||
ID int32 `json:"id" gorm:"column:id;primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" gorm:"column:updated_at"`
|
||||
DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"column:deleted_at"`
|
||||
}
|
||||
|
||||
func (m *Model) GetID() int32 {
|
||||
return m.ID
|
||||
}
|
||||
|
||||
func GetIDs[T IModel](models []T) []int32 {
|
||||
return u.Map(models, func(m T) int32 {
|
||||
return m.GetID()
|
||||
})
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package announcement
|
||||
|
||||
type Type int32
|
||||
|
||||
const (
|
||||
TypeNormal Type = iota + 1 // 普通公告
|
||||
)
|
||||
@@ -1,34 +0,0 @@
|
||||
package bill
|
||||
|
||||
import (
|
||||
"github.com/shopspring/decimal"
|
||||
m "platform/web/models"
|
||||
)
|
||||
|
||||
func NewForRecharge(uid int32, billNo string, info string, amount decimal.Decimal, trade *m.Trade) *m.Bill {
|
||||
return &m.Bill{
|
||||
UserID: uid,
|
||||
BillNo: billNo,
|
||||
TradeID: &trade.ID,
|
||||
Type: int32(TypeRecharge),
|
||||
Info: &info,
|
||||
Amount: amount,
|
||||
}
|
||||
}
|
||||
|
||||
func NewForConsume(uid int32, billNo string, info string, amount decimal.Decimal, resource *m.Resource, trade ...*m.Trade) *m.Bill {
|
||||
var bill = &m.Bill{
|
||||
UserID: uid,
|
||||
BillNo: billNo,
|
||||
ResourceID: &resource.ID,
|
||||
Type: int32(TypeConsume),
|
||||
Info: &info,
|
||||
Amount: amount,
|
||||
}
|
||||
|
||||
if len(trade) > 0 {
|
||||
bill.TradeID = &trade[0].ID
|
||||
}
|
||||
|
||||
return bill
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package bill
|
||||
|
||||
type Type int32
|
||||
|
||||
const (
|
||||
TypeConsume Type = iota + 1 // 消费
|
||||
TypeRefund // 退款
|
||||
TypeRecharge // 充值
|
||||
)
|
||||
@@ -1,9 +0,0 @@
|
||||
package channel
|
||||
|
||||
type Protocol int32
|
||||
|
||||
const (
|
||||
ProtocolHttp Protocol = iota + 1
|
||||
ProtocolHttps
|
||||
ProtocolSocks5
|
||||
)
|
||||
@@ -1,17 +0,0 @@
|
||||
package client
|
||||
|
||||
type Spec int32
|
||||
|
||||
const (
|
||||
SpecNative Spec = iota + 1 // 原生客户端
|
||||
SpecBrowser // 浏览器客户端
|
||||
SpecWeb // Web 服务
|
||||
SpecApi // Api 服务
|
||||
)
|
||||
|
||||
type Type int32
|
||||
|
||||
const (
|
||||
TypeNormal Type = iota // 普通客户端
|
||||
TypeInternal // 内部客户端
|
||||
)
|
||||
@@ -1,9 +0,0 @@
|
||||
package coupon
|
||||
|
||||
type Status int32
|
||||
|
||||
const (
|
||||
StatusUnused = iota // 未使用
|
||||
StatusUsed // 已使用
|
||||
StatusExpired // 已过期
|
||||
)
|
||||
@@ -1,43 +0,0 @@
|
||||
package edge
|
||||
|
||||
import "strings"
|
||||
|
||||
type ISP int32
|
||||
|
||||
const (
|
||||
IspUnknown ISP = iota // 未知
|
||||
IspChinaTelecom // 中国电信
|
||||
IspChinaUnicom // 中国联通
|
||||
IspChinaMobile // 中国移动
|
||||
)
|
||||
|
||||
func ISPFromStr(str string) ISP {
|
||||
switch {
|
||||
case strings.Contains(str, "电信"):
|
||||
return IspChinaTelecom
|
||||
case strings.Contains(str, "联通"):
|
||||
return IspChinaUnicom
|
||||
case strings.Contains(str, "移动"):
|
||||
return IspChinaMobile
|
||||
}
|
||||
return IspUnknown
|
||||
}
|
||||
|
||||
func (isp ISP) String() string {
|
||||
switch isp {
|
||||
case IspChinaTelecom:
|
||||
return "电信"
|
||||
case IspChinaUnicom:
|
||||
return "联通"
|
||||
case IspChinaMobile:
|
||||
return "移动"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
type Type int32
|
||||
|
||||
const (
|
||||
TypeSelfHosted Type = iota + 1 // 自建节点
|
||||
)
|
||||
@@ -1,8 +0,0 @@
|
||||
package proxy
|
||||
|
||||
type Type int32
|
||||
|
||||
const (
|
||||
TypeThirdParty Type = iota + 1 // 三方代理
|
||||
TypeSelfHosted // 自建代理
|
||||
)
|
||||
@@ -1,9 +0,0 @@
|
||||
package refund
|
||||
|
||||
type Status int32
|
||||
|
||||
const (
|
||||
StatusHandling Status = iota + 1 // 待处理
|
||||
StatusSuccess // 已退款
|
||||
StatusRefused // 已拒绝
|
||||
)
|
||||
@@ -1,15 +0,0 @@
|
||||
package resource
|
||||
|
||||
type Type int32
|
||||
|
||||
const (
|
||||
TypeShort Type = iota + 1 // 短效动态
|
||||
TypeLong // 长效动态
|
||||
)
|
||||
|
||||
type Mode int32
|
||||
|
||||
const (
|
||||
ModeTime Mode = iota + 1 // 包时
|
||||
ModeCount // 包量
|
||||
)
|
||||
@@ -1,60 +0,0 @@
|
||||
package trade
|
||||
|
||||
import (
|
||||
m "platform/web/models"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
type Type int32
|
||||
|
||||
const (
|
||||
TypePurchase Type = iota + 1 // 购买
|
||||
TypeRecharge // 充值
|
||||
)
|
||||
|
||||
type Method int32
|
||||
|
||||
const (
|
||||
MethodAlipay Method = iota + 1 // 支付宝
|
||||
MethodWeChat // 微信
|
||||
MethodSft // 商福通
|
||||
MethodSftAlipay // 商福通渠道指定支付宝
|
||||
MethodSftWeChat // 商福通渠道指定微信
|
||||
)
|
||||
|
||||
type Platform int32
|
||||
|
||||
const (
|
||||
PlatformDesktop Platform = iota + 1 // 桌面网站
|
||||
PlatformMobile // 手机网站
|
||||
)
|
||||
|
||||
type Acquirer int32
|
||||
|
||||
const (
|
||||
AcquirerAlipay Acquirer = iota + 1 // 支付宝
|
||||
AcquirerWeChat // 微信
|
||||
AcquirerUnionPay // 银联
|
||||
)
|
||||
|
||||
type Status int32
|
||||
|
||||
const (
|
||||
StatusPending Status = iota // 待支付
|
||||
StatusSuccess // 已支付
|
||||
StatusCanceled // 已取消
|
||||
)
|
||||
|
||||
type ProductInfo interface {
|
||||
GetType() Type
|
||||
GetSubject() string
|
||||
GetAmount() decimal.Decimal
|
||||
Serialize() (string, error)
|
||||
Deserialize(str string) error
|
||||
}
|
||||
|
||||
type CompleteEvent interface {
|
||||
Check(t Type) (ProductInfo, bool)
|
||||
OnTradeComplete(info ProductInfo, trade *m.Trade) error
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package user
|
||||
|
||||
type IdType int32
|
||||
|
||||
const (
|
||||
IdTypeNone IdType = iota // 未认证
|
||||
IdTypePersonal // 个人认证
|
||||
IdTypeEnterprise // 企业认证
|
||||
)
|
||||
|
||||
type Status int32
|
||||
|
||||
const (
|
||||
StatusDisabled Status = iota // 禁用
|
||||
StatusEnabled // 启用
|
||||
)
|
||||
@@ -2,14 +2,20 @@ package events
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/hibiken/asynq"
|
||||
"log/slog"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
)
|
||||
|
||||
const RemoveChannel = "channel:remove"
|
||||
|
||||
func NewRemoveChannel(ids []int32) *asynq.Task {
|
||||
bytes, err := json.Marshal(ids)
|
||||
type RemoveChannelData struct {
|
||||
Batch string `json:"batch"`
|
||||
IDs []int32 `json:"ids"`
|
||||
}
|
||||
|
||||
func NewRemoveChannel(data RemoveChannelData) *asynq.Task {
|
||||
bytes, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
slog.Error("序列化删除通道任务失败", "error", err)
|
||||
return nil
|
||||
|
||||
9
web/events/proxy.go
Normal file
9
web/events/proxy.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package events
|
||||
|
||||
import "github.com/hibiken/asynq"
|
||||
|
||||
const FlushGateway = "gateway:flush"
|
||||
|
||||
func NewFlushGateway() *asynq.Task {
|
||||
return asynq.NewTask(FlushGateway, nil)
|
||||
}
|
||||
@@ -3,7 +3,8 @@ package events
|
||||
import (
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
trade2 "platform/web/domains/trade"
|
||||
|
||||
m "platform/web/models"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
)
|
||||
@@ -12,7 +13,7 @@ const CancelTrade = "trade:update"
|
||||
|
||||
type CancelTradeData struct {
|
||||
TradeNo string `json:"trade_no" validate:"required"`
|
||||
Method trade2.Method `json:"method" validate:"required"`
|
||||
Method m.TradeMethod `json:"method" validate:"required"`
|
||||
}
|
||||
|
||||
func NewCancelTrade(data CancelTradeData) *asynq.Task {
|
||||
|
||||
32
web/globals/orm/inet.go
Normal file
32
web/globals/orm/inet.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package orm
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
)
|
||||
|
||||
type Inet struct {
|
||||
netip.Addr
|
||||
}
|
||||
|
||||
func (inet Inet) Value() (driver.Value, error) {
|
||||
return inet.MarshalBinary()
|
||||
}
|
||||
|
||||
func (inet *Inet) Scan(value any) (err error) {
|
||||
switch value := value.(type) {
|
||||
case []byte:
|
||||
return inet.UnmarshalBinary(value)
|
||||
default:
|
||||
return fmt.Errorf("不支持的类型: %T", value)
|
||||
}
|
||||
}
|
||||
|
||||
func ParseInet(ip string) (*Inet, error) {
|
||||
addr, err := netip.ParseAddr(ip)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Inet{addr}, nil
|
||||
}
|
||||
@@ -20,8 +20,7 @@ var formats = []string{
|
||||
"2006-01-02",
|
||||
}
|
||||
|
||||
//goland:noinspection GoMixedReceiverTypes
|
||||
func (ldt *LocalDateTime) Scan(value interface{}) (err error) {
|
||||
func (ldt *LocalDateTime) Scan(value any) (err error) {
|
||||
var t time.Time
|
||||
if strValue, ok := value.(string); ok {
|
||||
var timeValue time.Time
|
||||
@@ -50,35 +49,26 @@ func (ldt *LocalDateTime) Scan(value interface{}) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
//goland:noinspection GoMixedReceiverTypes
|
||||
func (ldt LocalDateTime) Value() (driver.Value, error) {
|
||||
return time.Time(ldt).Local(), nil
|
||||
}
|
||||
|
||||
// GormDataType gorm common data type
|
||||
//
|
||||
//goland:noinspection GoMixedReceiverTy
|
||||
//goland:noinspection GoMixedReceiverTypes
|
||||
func (ldt LocalDateTime) GormDataType() string {
|
||||
return "ldt"
|
||||
}
|
||||
|
||||
//goland:noinspection GoMixedReceiverTypes
|
||||
func (ldt LocalDateTime) GobEncode() ([]byte, error) {
|
||||
return time.Time(ldt).GobEncode()
|
||||
}
|
||||
|
||||
//goland:noinspection GoMixedReceiverTypes
|
||||
func (ldt *LocalDateTime) GobDecode(b []byte) error {
|
||||
return (*time.Time)(ldt).GobDecode(b)
|
||||
}
|
||||
|
||||
//goland:noinspection GoMixedReceiverTypes
|
||||
func (ldt LocalDateTime) MarshalJSON() ([]byte, error) {
|
||||
return time.Time(ldt).MarshalJSON()
|
||||
}
|
||||
|
||||
//goland:noinspection GoMixedReceiverTypes
|
||||
func (ldt *LocalDateTime) UnmarshalJSON(b []byte) error {
|
||||
return (*time.Time)(ldt).UnmarshalJSON(b)
|
||||
}
|
||||
|
||||
24
web/globals/orm/slice.go
Normal file
24
web/globals/orm/slice.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package orm
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Slice[T any] struct {
|
||||
Arr []T
|
||||
}
|
||||
|
||||
func (s Slice[T]) Value() (driver.Value, error) {
|
||||
return json.Marshal(s)
|
||||
}
|
||||
|
||||
func (s *Slice[T]) Scan(value any) error {
|
||||
switch value := value.(type) {
|
||||
case []byte:
|
||||
return json.Unmarshal(value, s)
|
||||
default:
|
||||
return fmt.Errorf("不支持的类型: %T", value)
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package handlers
|
||||
import (
|
||||
"platform/web/auth"
|
||||
"platform/web/core"
|
||||
"platform/web/globals/orm"
|
||||
q "platform/web/queries"
|
||||
"time"
|
||||
|
||||
@@ -39,13 +38,13 @@ func ListBill(c *fiber.Ctx) error {
|
||||
Where(q.Bill.UserID.Eq(authCtx.User.ID))
|
||||
|
||||
if req.Type != nil {
|
||||
do.Where(q.Bill.Type.Eq(int32(*req.Type)))
|
||||
do.Where(q.Bill.Type.Eq(int(*req.Type)))
|
||||
}
|
||||
if req.CreateAfter != nil {
|
||||
do.Where(q.Bill.CreatedAt.Gte(orm.LocalDateTime(*req.CreateAfter)))
|
||||
do.Where(q.Bill.CreatedAt.Gte(*req.CreateAfter))
|
||||
}
|
||||
if req.CreateBefore != nil {
|
||||
do.Where(q.Bill.CreatedAt.Lte(orm.LocalDateTime(*req.CreateBefore)))
|
||||
do.Where(q.Bill.CreatedAt.Lte(*req.CreateBefore))
|
||||
}
|
||||
if req.BillNo != nil && *req.BillNo != "" {
|
||||
do.Where(q.Bill.BillNo.Eq(*req.BillNo))
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"platform/pkg/u"
|
||||
"platform/web/auth"
|
||||
"platform/web/core"
|
||||
channel2 "platform/web/domains/channel"
|
||||
"platform/web/globals/orm"
|
||||
m "platform/web/models"
|
||||
q "platform/web/queries"
|
||||
s "platform/web/services"
|
||||
"time"
|
||||
@@ -40,18 +40,18 @@ func ListChannels(c *fiber.Ctx) error {
|
||||
Where(q.Channel.UserID.Eq(authContext.User.ID))
|
||||
switch req.AuthType {
|
||||
case s.ChannelAuthTypeIp:
|
||||
cond.Where(q.Channel.AuthIP.Is(true))
|
||||
cond.Where(q.Channel.Whitelists.IsNotNull())
|
||||
case s.ChannelAuthTypePass:
|
||||
cond.Where(q.Channel.AuthPass.Is(true))
|
||||
cond.Where(q.Channel.Username.IsNotNull(), q.Channel.Password.IsNotNull())
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if req.ExpireAfter != nil {
|
||||
cond.Where(q.Channel.Expiration.Gte(orm.LocalDateTime(*req.ExpireAfter)))
|
||||
cond.Where(q.Channel.ExpiredAt.Gte(*req.ExpireAfter))
|
||||
}
|
||||
if req.ExpireBefore != nil {
|
||||
cond.Where(q.Channel.Expiration.Lte(orm.LocalDateTime(*req.ExpireBefore)))
|
||||
cond.Where(q.Channel.ExpiredAt.Lte(*req.ExpireBefore))
|
||||
}
|
||||
|
||||
// 查询数据
|
||||
@@ -92,19 +92,19 @@ func ListChannels(c *fiber.Ctx) error {
|
||||
type CreateChannelReq struct {
|
||||
ResourceId int32 `json:"resource_id" validate:"required"`
|
||||
AuthType s.ChannelAuthType `json:"auth_type" validate:"required"`
|
||||
Protocol channel2.Protocol `json:"protocol" validate:"required"`
|
||||
Protocol int `json:"protocol" validate:"required"`
|
||||
Count int `json:"count" validate:"required"`
|
||||
Prov string `json:"prov"`
|
||||
City string `json:"city"`
|
||||
Isp string `json:"isp"`
|
||||
Prov *string `json:"prov"`
|
||||
City *string `json:"city"`
|
||||
Isp *int `json:"isp"`
|
||||
}
|
||||
|
||||
type CreateChannelRespItem struct {
|
||||
Proto channel2.Protocol `json:"-"`
|
||||
Host string `json:"host"`
|
||||
Port int32 `json:"port"`
|
||||
Username *string `json:"username,omitempty"`
|
||||
Password *string `json:"password,omitempty"`
|
||||
Proto int `json:"-"`
|
||||
Host string `json:"host"`
|
||||
Port uint16 `json:"port"`
|
||||
Username *string `json:"username,omitempty"`
|
||||
Password *string `json:"password,omitempty"`
|
||||
}
|
||||
|
||||
func CreateChannel(c *fiber.Ctx) error {
|
||||
@@ -115,48 +115,32 @@ func CreateChannel(c *fiber.Ctx) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 检查用户其他权限
|
||||
user := authCtx.User
|
||||
if user.IDToken == nil || *user.IDToken == "" {
|
||||
return fiber.NewError(fiber.StatusForbidden, "账号未实名")
|
||||
}
|
||||
|
||||
count, err := q.Whitelist.Where(
|
||||
q.Whitelist.UserID.Eq(user.ID),
|
||||
q.Whitelist.Host.Eq(c.IP()),
|
||||
).Count()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if count == 0 {
|
||||
return fiber.NewError(fiber.StatusForbidden, fmt.Sprintf("非白名单IP %s", c.IP()))
|
||||
}
|
||||
|
||||
// 解析参数
|
||||
req := new(CreateChannelReq)
|
||||
if err := c.BodyParser(req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var isp string
|
||||
switch req.Isp {
|
||||
case "1":
|
||||
isp = "电信"
|
||||
case "2":
|
||||
isp = "联通"
|
||||
case "3":
|
||||
isp = "移动"
|
||||
ip, err := netip.ParseAddr(c.Get(core.HeaderUserIP))
|
||||
if err != nil {
|
||||
return core.NewBizErr("解析请求头客户端 IP 地址失败", err)
|
||||
}
|
||||
|
||||
// 创建通道
|
||||
result, err := s.Channel.CreateChannel(
|
||||
c,
|
||||
result, err := s.Channel.CreateChannels(
|
||||
ip,
|
||||
user.ID,
|
||||
req.ResourceId,
|
||||
req.Protocol,
|
||||
req.AuthType,
|
||||
req.AuthType == s.ChannelAuthTypeIp,
|
||||
req.AuthType == s.ChannelAuthTypePass,
|
||||
req.Count,
|
||||
s.EdgeFilter{
|
||||
Isp: isp,
|
||||
Isp: u.ElseTo(req.Isp, m.ToEdgeISP),
|
||||
Prov: req.Prov,
|
||||
City: req.City,
|
||||
},
|
||||
@@ -170,8 +154,8 @@ func CreateChannel(c *fiber.Ctx) error {
|
||||
for i, channel := range result {
|
||||
resp[i] = &CreateChannelRespItem{
|
||||
Proto: req.Protocol,
|
||||
Host: channel.ProxyHost,
|
||||
Port: channel.ProxyPort,
|
||||
Host: channel.Proxy.IP.String(),
|
||||
Port: channel.Port,
|
||||
}
|
||||
if req.AuthType == s.ChannelAuthTypePass {
|
||||
resp[i].Username = channel.Username
|
||||
@@ -188,12 +172,13 @@ type CreateChannelResultType string
|
||||
// region RemoveChannels
|
||||
|
||||
type RemoveChannelsReq struct {
|
||||
ByIds []int32 `json:"by_ids" validate:"required"`
|
||||
Batch string `json:"batch" validate:"required"`
|
||||
Ids []int32 `json:"ids" validate:"required"`
|
||||
}
|
||||
|
||||
func RemoveChannels(c *fiber.Ctx) error {
|
||||
// 检查权限
|
||||
authCtx, err := auth.GetAuthCtx(c).PermitUser()
|
||||
_, err := auth.GetAuthCtx(c).PermitOfficialClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -205,7 +190,7 @@ func RemoveChannels(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// 删除通道
|
||||
err = s.Channel.RemoveChannels(req.ByIds, authCtx.User.ID)
|
||||
err = s.Channel.RemoveChannels(req.Batch, req.Ids)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,20 +1,8 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log/slog"
|
||||
"platform/pkg/u"
|
||||
"platform/web/auth"
|
||||
edge2 "platform/web/domains/edge"
|
||||
proxy2 "platform/web/domains/proxy"
|
||||
g "platform/web/globals"
|
||||
m "platform/web/models"
|
||||
q "platform/web/queries"
|
||||
s "platform/web/services"
|
||||
|
||||
"gorm.io/gen/field"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
@@ -29,80 +17,82 @@ type RegisterEdgeResp struct {
|
||||
}
|
||||
|
||||
func AssignEdge(c *fiber.Ctx) (err error) {
|
||||
|
||||
// 验证请求参数
|
||||
var req = new(RegisterEdgeReq)
|
||||
err = g.Validator.Validate(c, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 全局锁,防止并发注册
|
||||
var mutex = g.Redsync.NewMutex("edge:discovery")
|
||||
if err := mutex.Lock(); err != nil {
|
||||
return errors.New("服务繁忙,请稍后重试")
|
||||
}
|
||||
defer func() {
|
||||
if ok, err := mutex.Unlock(); err != nil {
|
||||
slog.Error("解锁失败", slog.Bool("ok", ok), slog.Any("err", err))
|
||||
}
|
||||
}()
|
||||
|
||||
// 检查节点
|
||||
var fwd *m.Proxy
|
||||
var edge *m.Edge
|
||||
edge, err = q.Edge.
|
||||
Where(q.Edge.Name.Eq(req.Name)).
|
||||
Take()
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 挑选合适的转发服务
|
||||
fwd, err = q.Proxy.
|
||||
LeftJoin(q.Edge, q.Edge.ProxyID.EqCol(q.Proxy.ID), q.Edge.Status.Eq(1)).
|
||||
Select(q.Proxy.ALL, q.Edge.ALL.Count().As("count")).
|
||||
Where(q.Proxy.Type.Eq(int32(proxy2.TypeSelfHosted))).
|
||||
Group(q.Proxy.ID).
|
||||
Order(field.NewField("", "count").Desc()).
|
||||
First()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 保存节点信息
|
||||
edge = &m.Edge{
|
||||
Name: req.Name,
|
||||
Version: int32(req.Version),
|
||||
Type: int32(edge2.TypeSelfHosted),
|
||||
ProxyID: &fwd.ID,
|
||||
}
|
||||
err = q.Edge.Create(edge)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if err == nil {
|
||||
// 获取已配置的转发服务
|
||||
fwd, err = q.Proxy.
|
||||
Where(q.Proxy.ID.Eq(*edge.ProxyID)).
|
||||
Take()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 节点已存在,更新版本号
|
||||
if edge.Version < int32(req.Version) {
|
||||
_, err = q.Edge.
|
||||
Where(q.Edge.ID.Eq(edge.ID)).
|
||||
UpdateSimple(q.Edge.Version.Value(int32(req.Version)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
|
||||
// 返回服务地址
|
||||
return c.JSON(RegisterEdgeResp{
|
||||
Id: edge.ID,
|
||||
Host: fwd.Host,
|
||||
return c.JSON(map[string]any{
|
||||
"error": "接口暂不可用",
|
||||
})
|
||||
// // 验证请求参数
|
||||
// var req = new(RegisterEdgeReq)
|
||||
// err = g.Validator.Validate(c, req)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// // 全局锁,防止并发注册
|
||||
// var mutex = g.Redsync.NewMutex("edge:discovery")
|
||||
// if err := mutex.Lock(); err != nil {
|
||||
// return errors.New("服务繁忙,请稍后重试")
|
||||
// }
|
||||
// defer func() {
|
||||
// if ok, err := mutex.Unlock(); err != nil {
|
||||
// slog.Error("解锁失败", slog.Bool("ok", ok), slog.Any("err", err))
|
||||
// }
|
||||
// }()
|
||||
|
||||
// // 检查节点
|
||||
// var fwd *m.Proxy
|
||||
// var edge *m.Edge
|
||||
// edge, err = q.Edge.
|
||||
// Where(q.Edge.Mac.Eq(req.Name)).
|
||||
// Take()
|
||||
// if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// // 挑选合适的转发服务
|
||||
// fwd, err = q.Proxy.
|
||||
// LeftJoin(q.Edge, q.Edge.ProxyID.EqCol(q.Proxy.ID), q.Edge.Status.Eq(1)).
|
||||
// Select(q.Proxy.ALL, q.Edge.ALL.Count().As("count")).
|
||||
// Where(q.Proxy.Type.Eq(int32(proxy2.TypeSelfHosted))).
|
||||
// Group(q.Proxy.ID).
|
||||
// Order(field.NewField("", "count").Desc()).
|
||||
// First()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// // 保存节点信息
|
||||
// edge = &m.Edge{
|
||||
// Name: req.Name,
|
||||
// Version: int32(req.Version),
|
||||
// Type: int32(edge2.TypeSelfHosted),
|
||||
// ProxyID: &fwd.ID,
|
||||
// }
|
||||
// err = q.Edge.Create(edge)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// } else if err == nil {
|
||||
// // 获取已配置的转发服务
|
||||
// fwd, err = q.Proxy.
|
||||
// Where(q.Proxy.ID.Eq(*edge.ProxyID)).
|
||||
// Take()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// // 节点已存在,更新版本号
|
||||
// if edge.Version < int32(req.Version) {
|
||||
// _, err = q.Edge.
|
||||
// Where(q.Edge.ID.Eq(edge.ID)).
|
||||
// UpdateSimple(q.Edge.Version.Value(int32(req.Version)))
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// // 返回服务地址
|
||||
// return c.JSON(RegisterEdgeResp{
|
||||
// Id: edge.ID,
|
||||
// Host: fwd.Host,
|
||||
// })
|
||||
}
|
||||
|
||||
type AllEdgesAvailableReq struct {
|
||||
@@ -120,36 +110,40 @@ type AllEdgesAvailableRespItem struct {
|
||||
}
|
||||
|
||||
func AllEdgesAvailable(c *fiber.Ctx) (err error) {
|
||||
// 检查权限
|
||||
_, err = auth.GetAuthCtx(c).PermitSecretClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(map[string]any{
|
||||
"error": "接口暂不可用",
|
||||
})
|
||||
|
||||
// 验证请求参数
|
||||
var req = new(AllEdgesAvailableReq)
|
||||
err = g.Validator.Validate(c, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// // 检查权限
|
||||
// _, err = auth.GetAuthCtx(c).PermitSecretClient()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// 获取可用的转发服务
|
||||
infos, err := s.Edge.AllEdges(req.Count, req.EdgeFilter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// // 验证请求参数
|
||||
// var req = new(AllEdgesAvailableReq)
|
||||
// err = g.Validator.Validate(c, req)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// 返回结果
|
||||
var edges = make([]AllEdgesAvailableRespItem, len(infos))
|
||||
for i, info := range infos {
|
||||
edges[i] = AllEdgesAvailableRespItem{
|
||||
Ip: info.Host,
|
||||
Port: u.Z(info.ProxyPort),
|
||||
Isp: edge2.ISP(info.Isp).String(),
|
||||
Prov: info.Prov,
|
||||
City: info.City,
|
||||
Status: info.Status,
|
||||
}
|
||||
}
|
||||
return c.JSON(edges)
|
||||
// // 获取可用的转发服务
|
||||
// infos, err := s.Edge.AllEdges(req.Count, req.EdgeFilter)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// // 返回结果
|
||||
// var edges = make([]AllEdgesAvailableRespItem, len(infos))
|
||||
// for i, info := range infos {
|
||||
// edges[i] = AllEdgesAvailableRespItem{
|
||||
// Ip: info.Host,
|
||||
// Port: u.Z(info.ProxyPort),
|
||||
// Isp: edge2.ISP(info.Isp).String(),
|
||||
// Prov: info.Prov,
|
||||
// City: info.City,
|
||||
// Status: info.Status,
|
||||
// }
|
||||
// }
|
||||
// return c.JSON(edges)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
// region Identify
|
||||
|
||||
type IdentifyReq struct {
|
||||
Type int32 `json:"type" validate:"required,oneof=1 2"`
|
||||
Type int `json:"type" validate:"required,oneof=1 2"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
IdenNo string `json:"iden_no" validate:"required"`
|
||||
}
|
||||
@@ -173,7 +173,7 @@ func IdentifyCallback(c *fiber.Ctx) error {
|
||||
q.User.Name,
|
||||
).
|
||||
Updates(m.User{
|
||||
IDType: info.Type,
|
||||
IDType: m.UserIDType(info.Type),
|
||||
IDNo: &info.IdNo,
|
||||
IDToken: &info.Token,
|
||||
Name: &info.Name,
|
||||
@@ -202,7 +202,7 @@ func idenKey(id string) string {
|
||||
|
||||
type idenInfo struct {
|
||||
Uid int32 `json:"uid"`
|
||||
Type int32 `json:"type"`
|
||||
Type int `json:"type"`
|
||||
Name string `json:"name"`
|
||||
IdNo string `json:"id_no"`
|
||||
Token string `json:"token"`
|
||||
|
||||
@@ -1,26 +1,9 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base32"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"platform/pkg/u"
|
||||
auth2 "platform/web/auth"
|
||||
"platform/web/core"
|
||||
edge2 "platform/web/domains/edge"
|
||||
proxy2 "platform/web/domains/proxy"
|
||||
g "platform/web/globals"
|
||||
"platform/web/globals/orm"
|
||||
m "platform/web/models"
|
||||
q "platform/web/queries"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
|
||||
"gorm.io/gen/field"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
// region 报告上线
|
||||
@@ -38,103 +21,106 @@ type ProxyReportOnlineResp struct {
|
||||
}
|
||||
|
||||
func ProxyReportOnline(c *fiber.Ctx) (err error) {
|
||||
|
||||
// 检查接口权限
|
||||
_, err = auth2.GetAuthCtx(c).PermitSecretClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 验证请求参数
|
||||
var req = new(ProxyReportOnlineReq)
|
||||
err = g.Validator.Validate(c, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 创建代理
|
||||
var ip = c.Context().RemoteIP()
|
||||
|
||||
var secretBytes = make([]byte, 16)
|
||||
if _, err := rand.Read(secretBytes); err != nil {
|
||||
return err
|
||||
}
|
||||
var secret = base32.StdEncoding.
|
||||
WithPadding(base32.NoPadding).
|
||||
EncodeToString(secretBytes)
|
||||
slog.Debug("生成随机密钥", "ip", ip, "secret", secret)
|
||||
|
||||
var proxy = &m.Proxy{
|
||||
Name: req.Name,
|
||||
Version: int32(req.Version),
|
||||
Type: int32(proxy2.TypeSelfHosted),
|
||||
Host: ip.String(),
|
||||
Secret: &secret,
|
||||
Status: 1,
|
||||
}
|
||||
err = q.Proxy.
|
||||
Clauses(clause.OnConflict{
|
||||
UpdateAll: true,
|
||||
Columns: []clause.Column{
|
||||
{Name: q.Proxy.Name.ColumnName().String()},
|
||||
},
|
||||
}).
|
||||
Create(proxy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 获取边缘节点信息
|
||||
data, err := q.Edge.Where(
|
||||
q.Edge.ProxyID.Eq(proxy.ID),
|
||||
).Find()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
edges := make([]*ProxyEdge, len(data))
|
||||
for i, edge := range data {
|
||||
edges[i] = &ProxyEdge{
|
||||
Id: edge.ID,
|
||||
Port: edge.ProxyPort,
|
||||
Prov: &edge.Prov,
|
||||
City: &edge.City,
|
||||
Isp: u.P(edge2.ISP(edge.Isp).String()),
|
||||
Status: &edge.Status,
|
||||
Loss: edge.Loss,
|
||||
Rtt: edge.Rtt,
|
||||
}
|
||||
}
|
||||
|
||||
// 获取许可配置
|
||||
channels, err := q.Channel.Where(
|
||||
q.Channel.ProxyID.Eq(proxy.ID),
|
||||
q.Channel.Expiration.Gt(orm.LocalDateTime(time.Now())),
|
||||
).Find()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var permits = make([]*ProxyPermit, len(channels))
|
||||
for i, channel := range channels {
|
||||
if channel.EdgeID == nil {
|
||||
return core.NewBizErr(fmt.Sprintf("权限解析异常,通道缺少边缘节点ID %d", channel.ID))
|
||||
}
|
||||
permits[i] = &ProxyPermit{
|
||||
Id: *channel.EdgeID,
|
||||
Expire: time.Time(channel.Expiration),
|
||||
Whitelists: u.P(strings.Split(u.Z(channel.Whitelists), ",")),
|
||||
Username: channel.Username,
|
||||
Password: channel.Password,
|
||||
}
|
||||
}
|
||||
|
||||
slog.Debug("注册转发服务", "ip", ip, "id", proxy.ID)
|
||||
return c.JSON(&ProxyReportOnlineResp{
|
||||
Id: proxy.ID,
|
||||
Secret: secret,
|
||||
Edges: edges,
|
||||
Permits: permits,
|
||||
return c.JSON(map[string]any{
|
||||
"error": "接口暂不可用",
|
||||
})
|
||||
|
||||
// // 检查接口权限
|
||||
// _, err = auth2.GetAuthCtx(c).PermitSecretClient()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// // 验证请求参数
|
||||
// var req = new(ProxyReportOnlineReq)
|
||||
// err = g.Validator.Validate(c, req)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// // 创建代理
|
||||
// var ip = c.Context().RemoteIP()
|
||||
|
||||
// var secretBytes = make([]byte, 16)
|
||||
// if _, err := rand.Read(secretBytes); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// var secret = base32.StdEncoding.
|
||||
// WithPadding(base32.NoPadding).
|
||||
// EncodeToString(secretBytes)
|
||||
// slog.Debug("生成随机密钥", "ip", ip, "secret", secret)
|
||||
|
||||
// var proxy = &m.Proxy{
|
||||
// Mac: req.Name,
|
||||
// Version: int32(req.Version),
|
||||
// Type: m.ProxyTypeSelfHosted,
|
||||
// IP: ip,
|
||||
// Secret: &secret,
|
||||
// Status: 1,
|
||||
// }
|
||||
// err = q.Proxy.
|
||||
// Clauses(clause.OnConflict{
|
||||
// UpdateAll: true,
|
||||
// Columns: []clause.Column{
|
||||
// {Name: q.Proxy.Mac.ColumnName().String()},
|
||||
// },
|
||||
// }).
|
||||
// Create(proxy)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// // 获取边缘节点信息
|
||||
// data, err := q.Edge.Where(
|
||||
// q.Edge.ProxyID.Eq(proxy.ID),
|
||||
// ).Find()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// edges := make([]*ProxyEdge, len(data))
|
||||
// for i, edge := range data {
|
||||
// edges[i] = &ProxyEdge{
|
||||
// Id: edge.ID,
|
||||
// Port: edge.ProxyPort,
|
||||
// Prov: &edge.Prov,
|
||||
// City: &edge.City,
|
||||
// Isp: u.P(edge2.ISP(edge.Isp).String()),
|
||||
// Status: &edge.Status,
|
||||
// Loss: edge.Loss,
|
||||
// Rtt: edge.Rtt,
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 获取许可配置
|
||||
// channels, err := q.Channel.Where(
|
||||
// q.Channel.ProxyID.Eq(proxy.ID),
|
||||
// q.Channel.Expiration.Gt(orm.LocalDateTime(time.Now())),
|
||||
// ).Find()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// var permits = make([]*ProxyPermit, len(channels))
|
||||
// for i, channel := range channels {
|
||||
// if channel.EdgeID == nil {
|
||||
// return core.NewBizErr(fmt.Sprintf("权限解析异常,通道缺少边缘节点ID %d", channel.ID))
|
||||
// }
|
||||
// permits[i] = &ProxyPermit{
|
||||
// Id: *channel.EdgeID,
|
||||
// Expire: time.Time(channel.Expiration),
|
||||
// Whitelists: u.P(strings.Split(u.Z(channel.Whitelists), ",")),
|
||||
// Username: channel.Username,
|
||||
// Password: channel.Password,
|
||||
// }
|
||||
// }
|
||||
|
||||
// slog.Debug("注册转发服务", "ip", ip, "id", proxy.ID)
|
||||
// return c.JSON(&ProxyReportOnlineResp{
|
||||
// Id: proxy.ID,
|
||||
// Secret: secret,
|
||||
// Edges: edges,
|
||||
// Permits: permits,
|
||||
// })
|
||||
}
|
||||
|
||||
// endregion
|
||||
@@ -146,36 +132,40 @@ type ProxyReportOfflineReq struct {
|
||||
}
|
||||
|
||||
func ProxyReportOffline(c *fiber.Ctx) (err error) {
|
||||
// 检查接口权限
|
||||
_, err = auth2.GetAuthCtx(c).PermitSecretClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(map[string]any{
|
||||
"error": "接口暂不可用",
|
||||
})
|
||||
|
||||
// 验证请求参数
|
||||
var req = new(ProxyReportOfflineReq)
|
||||
err = g.Validator.Validate(c, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// // 检查接口权限
|
||||
// _, err = auth2.GetAuthCtx(c).PermitSecretClient()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// 下线转发服务
|
||||
_, err = q.Proxy.
|
||||
Where(q.Proxy.ID.Eq(req.Id)).
|
||||
UpdateSimple(q.Proxy.Status.Value(0))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// // 验证请求参数
|
||||
// var req = new(ProxyReportOfflineReq)
|
||||
// err = g.Validator.Validate(c, req)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// 下线所有相关的边缘节点
|
||||
_, err = q.Edge.
|
||||
Where(q.Edge.ProxyID.Eq(req.Id)).
|
||||
UpdateSimple(q.Edge.Status.Value(0))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// // 下线转发服务
|
||||
// _, err = q.Proxy.
|
||||
// Where(q.Proxy.ID.Eq(req.Id)).
|
||||
// UpdateSimple(q.Proxy.Status.Value(0))
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
return nil
|
||||
// // 下线所有相关的边缘节点
|
||||
// _, err = q.Edge.
|
||||
// Where(q.Edge.ProxyID.Eq(req.Id)).
|
||||
// UpdateSimple(q.Edge.Status.Value(0))
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// return nil
|
||||
}
|
||||
|
||||
// endregion
|
||||
@@ -188,157 +178,161 @@ type ProxyReportUpdateReq struct {
|
||||
}
|
||||
|
||||
func ProxyReportUpdate(c *fiber.Ctx) (err error) {
|
||||
// 检查接口权限
|
||||
_, err = auth2.GetAuthCtx(c).PermitSecretClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 验证请求参数
|
||||
var req = new(ProxyReportUpdateReq)
|
||||
err = g.Validator.Validate(c, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 更新节点信息
|
||||
var idsActive = make([]int32, 0, len(req.Edges))
|
||||
var idsInactive = make([]int32, 0, len(req.Edges))
|
||||
var idsIspUnknown = make([]int32, 0, len(req.Edges))
|
||||
var idsIspTelecom = make([]int32, 0, len(req.Edges))
|
||||
var idsIspUnicom = make([]int32, 0, len(req.Edges))
|
||||
var idsIspMobile = make([]int32, 0, len(req.Edges))
|
||||
var otherEdges = make([]*ProxyEdge, 0, len(req.Edges))
|
||||
for _, edge := range req.Edges {
|
||||
|
||||
// 检查更新ISP
|
||||
if edge.Isp != nil {
|
||||
switch edge2.ISPFromStr(*edge.Isp) {
|
||||
case edge2.IspUnknown:
|
||||
idsIspUnknown = append(idsIspUnknown, edge.Id)
|
||||
case edge2.IspChinaTelecom:
|
||||
idsIspTelecom = append(idsIspTelecom, edge.Id)
|
||||
case edge2.IspChinaUnicom:
|
||||
idsIspUnicom = append(idsIspUnicom, edge.Id)
|
||||
case edge2.IspChinaMobile:
|
||||
idsIspMobile = append(idsIspMobile, edge.Id)
|
||||
}
|
||||
}
|
||||
|
||||
// 检查更新状态
|
||||
if edge.Status != nil {
|
||||
if *edge.Status == 1 {
|
||||
idsActive = append(idsActive, edge.Id)
|
||||
} else {
|
||||
idsInactive = append(idsInactive, edge.Id)
|
||||
}
|
||||
}
|
||||
|
||||
// 无法分类更新
|
||||
if edge.Host != nil || edge.Port != nil || edge.Prov != nil || edge.City != nil {
|
||||
otherEdges = append(otherEdges, edge)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
slog.Debug("更新边缘节点信息",
|
||||
"active", len(idsActive),
|
||||
"inactive", len(idsInactive),
|
||||
"isp_unknown", len(idsIspUnknown),
|
||||
"isp_telecom", len(idsIspTelecom),
|
||||
"isp_unicom", len(idsIspUnicom),
|
||||
"isp_mobile", len(idsIspMobile),
|
||||
"other_edges", len(otherEdges),
|
||||
)
|
||||
|
||||
err = q.Q.Transaction(func(q *q.Query) error {
|
||||
// 更新边缘节点状态
|
||||
if len(idsActive) > 0 {
|
||||
_, err = q.Edge.Debug().
|
||||
Where(q.Edge.ID.In(idsActive...)).
|
||||
UpdateSimple(q.Edge.Status.Value(1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(idsInactive) > 0 {
|
||||
_, err = q.Edge.Debug().
|
||||
Where(q.Edge.ID.In(idsInactive...)).
|
||||
UpdateSimple(q.Edge.Status.Value(0))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 更新边缘节点ISP
|
||||
if len(idsIspUnknown) > 0 {
|
||||
_, err = q.Edge.Debug().
|
||||
Where(q.Edge.ID.In(idsIspUnknown...)).
|
||||
UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspUnknown)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(idsIspTelecom) > 0 {
|
||||
_, err = q.Edge.Debug().
|
||||
Where(q.Edge.ID.In(idsIspTelecom...)).
|
||||
UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspChinaTelecom)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(idsIspUnicom) > 0 {
|
||||
_, err = q.Edge.Debug().
|
||||
Where(q.Edge.ID.In(idsIspUnicom...)).
|
||||
UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspChinaUnicom)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(idsIspMobile) > 0 {
|
||||
_, err = q.Edge.Debug().
|
||||
Where(q.Edge.ID.In(idsIspMobile...)).
|
||||
UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspChinaMobile)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 更新其他边缘节点信息
|
||||
for _, edge := range otherEdges {
|
||||
do := q.Edge.Debug().Where(q.Edge.ID.Eq(edge.Id))
|
||||
|
||||
var assigns = make([]field.AssignExpr, 0, 5)
|
||||
if edge.Host != nil {
|
||||
assigns = append(assigns, q.Edge.Host.Value(*edge.Host))
|
||||
}
|
||||
if edge.Port != nil {
|
||||
assigns = append(assigns, q.Edge.ProxyPort.Value(*edge.Port))
|
||||
}
|
||||
if edge.Prov != nil {
|
||||
assigns = append(assigns, q.Edge.Prov.Value(*edge.Prov))
|
||||
}
|
||||
if edge.City != nil {
|
||||
assigns = append(assigns, q.Edge.City.Value(*edge.City))
|
||||
}
|
||||
|
||||
// 更新边缘节点
|
||||
_, err := do.UpdateSimple(assigns...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("更新边缘节点 %d 失败: %w", edge.Id, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return c.JSON(map[string]any{
|
||||
"error": "接口暂不可用",
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
// // 检查接口权限
|
||||
// _, err = auth2.GetAuthCtx(c).PermitSecretClient()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// // 验证请求参数
|
||||
// var req = new(ProxyReportUpdateReq)
|
||||
// err = g.Validator.Validate(c, req)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// // 更新节点信息
|
||||
// var idsActive = make([]int32, 0, len(req.Edges))
|
||||
// var idsInactive = make([]int32, 0, len(req.Edges))
|
||||
// var idsIspUnknown = make([]int32, 0, len(req.Edges))
|
||||
// var idsIspTelecom = make([]int32, 0, len(req.Edges))
|
||||
// var idsIspUnicom = make([]int32, 0, len(req.Edges))
|
||||
// var idsIspMobile = make([]int32, 0, len(req.Edges))
|
||||
// var otherEdges = make([]*ProxyEdge, 0, len(req.Edges))
|
||||
// for _, edge := range req.Edges {
|
||||
|
||||
// // 检查更新ISP
|
||||
// if edge.Isp != nil {
|
||||
// switch edge2.ISPFromStr(*edge.Isp) {
|
||||
// case edge2.IspUnknown:
|
||||
// idsIspUnknown = append(idsIspUnknown, edge.Id)
|
||||
// case edge2.IspChinaTelecom:
|
||||
// idsIspTelecom = append(idsIspTelecom, edge.Id)
|
||||
// case edge2.IspChinaUnicom:
|
||||
// idsIspUnicom = append(idsIspUnicom, edge.Id)
|
||||
// case edge2.IspChinaMobile:
|
||||
// idsIspMobile = append(idsIspMobile, edge.Id)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 检查更新状态
|
||||
// if edge.Status != nil {
|
||||
// if *edge.Status == 1 {
|
||||
// idsActive = append(idsActive, edge.Id)
|
||||
// } else {
|
||||
// idsInactive = append(idsInactive, edge.Id)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 无法分类更新
|
||||
// if edge.Host != nil || edge.Port != nil || edge.Prov != nil || edge.City != nil {
|
||||
// otherEdges = append(otherEdges, edge)
|
||||
// continue
|
||||
// }
|
||||
// }
|
||||
|
||||
// slog.Debug("更新边缘节点信息",
|
||||
// "active", len(idsActive),
|
||||
// "inactive", len(idsInactive),
|
||||
// "isp_unknown", len(idsIspUnknown),
|
||||
// "isp_telecom", len(idsIspTelecom),
|
||||
// "isp_unicom", len(idsIspUnicom),
|
||||
// "isp_mobile", len(idsIspMobile),
|
||||
// "other_edges", len(otherEdges),
|
||||
// )
|
||||
|
||||
// err = q.Q.Transaction(func(q *q.Query) error {
|
||||
// // 更新边缘节点状态
|
||||
// if len(idsActive) > 0 {
|
||||
// _, err = q.Edge.Debug().
|
||||
// Where(q.Edge.ID.In(idsActive...)).
|
||||
// UpdateSimple(q.Edge.Status.Value(1))
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
|
||||
// if len(idsInactive) > 0 {
|
||||
// _, err = q.Edge.Debug().
|
||||
// Where(q.Edge.ID.In(idsInactive...)).
|
||||
// UpdateSimple(q.Edge.Status.Value(0))
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 更新边缘节点ISP
|
||||
// if len(idsIspUnknown) > 0 {
|
||||
// _, err = q.Edge.Debug().
|
||||
// Where(q.Edge.ID.In(idsIspUnknown...)).
|
||||
// UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspUnknown)))
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
|
||||
// if len(idsIspTelecom) > 0 {
|
||||
// _, err = q.Edge.Debug().
|
||||
// Where(q.Edge.ID.In(idsIspTelecom...)).
|
||||
// UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspChinaTelecom)))
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
|
||||
// if len(idsIspUnicom) > 0 {
|
||||
// _, err = q.Edge.Debug().
|
||||
// Where(q.Edge.ID.In(idsIspUnicom...)).
|
||||
// UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspChinaUnicom)))
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
|
||||
// if len(idsIspMobile) > 0 {
|
||||
// _, err = q.Edge.Debug().
|
||||
// Where(q.Edge.ID.In(idsIspMobile...)).
|
||||
// UpdateSimple(q.Edge.Isp.Value(int32(edge2.IspChinaMobile)))
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 更新其他边缘节点信息
|
||||
// for _, edge := range otherEdges {
|
||||
// do := q.Edge.Debug().Where(q.Edge.ID.Eq(edge.Id))
|
||||
|
||||
// var assigns = make([]field.AssignExpr, 0, 5)
|
||||
// if edge.Host != nil {
|
||||
// assigns = append(assigns, q.Edge.Host.Value(*edge.Host))
|
||||
// }
|
||||
// if edge.Port != nil {
|
||||
// assigns = append(assigns, q.Edge.ProxyPort.Value(*edge.Port))
|
||||
// }
|
||||
// if edge.Prov != nil {
|
||||
// assigns = append(assigns, q.Edge.Prov.Value(*edge.Prov))
|
||||
// }
|
||||
// if edge.City != nil {
|
||||
// assigns = append(assigns, q.Edge.City.Value(*edge.City))
|
||||
// }
|
||||
|
||||
// // 更新边缘节点
|
||||
// _, err := do.UpdateSimple(assigns...)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("更新边缘节点 %d 失败: %w", edge.Id, err)
|
||||
// }
|
||||
// }
|
||||
// return nil
|
||||
// })
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// return nil
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
@@ -4,9 +4,8 @@ import (
|
||||
"platform/pkg/u"
|
||||
"platform/web/auth"
|
||||
"platform/web/core"
|
||||
resource2 "platform/web/domains/resource"
|
||||
g "platform/web/globals"
|
||||
"platform/web/globals/orm"
|
||||
m "platform/web/models"
|
||||
q "platform/web/queries"
|
||||
s "platform/web/services"
|
||||
"time"
|
||||
@@ -43,7 +42,7 @@ func ListResourceShort(c *fiber.Ctx) error {
|
||||
// 查询套餐列表
|
||||
do := q.Resource.Where(
|
||||
q.Resource.UserID.Eq(authCtx.User.ID),
|
||||
q.Resource.Type.Eq(int32(resource2.TypeShort)),
|
||||
q.Resource.Type.Eq(int(m.ResourceTypeShort)),
|
||||
)
|
||||
if req.ResourceNo != nil && *req.ResourceNo != "" {
|
||||
do.Where(q.Resource.ResourceNo.Eq(*req.ResourceNo))
|
||||
@@ -52,19 +51,19 @@ func ListResourceShort(c *fiber.Ctx) error {
|
||||
do.Where(q.Resource.Active.Is(*req.Active))
|
||||
}
|
||||
if req.Type != nil {
|
||||
do.Where(q.ResourceShort.As(q.Resource.Short.Name()).Type.Eq(int32(*req.Type)))
|
||||
do.Where(q.ResourceShort.As(q.Resource.Short.Name()).Type.Eq(*req.Type))
|
||||
}
|
||||
if req.CreateAfter != nil {
|
||||
do.Where(q.Resource.CreatedAt.Gte(orm.LocalDateTime(*req.CreateAfter)))
|
||||
do.Where(q.Resource.CreatedAt.Gte(*req.CreateAfter))
|
||||
}
|
||||
if req.CreateBefore != nil {
|
||||
do.Where(q.Resource.CreatedAt.Lte(orm.LocalDateTime(*req.CreateBefore)))
|
||||
do.Where(q.Resource.CreatedAt.Lte(*req.CreateBefore))
|
||||
}
|
||||
if req.ExpireAfter != nil {
|
||||
do.Where(q.ResourceShort.As(q.Resource.Short.Name()).Expire.Gte(orm.LocalDateTime(*req.ExpireAfter)))
|
||||
do.Where(q.ResourceShort.As(q.Resource.Short.Name()).Expire.Gte(*req.ExpireAfter))
|
||||
}
|
||||
if req.ExpireBefore != nil {
|
||||
do.Where(q.ResourceShort.As(q.Resource.Short.Name()).Expire.Lte(orm.LocalDateTime(*req.ExpireBefore)))
|
||||
do.Where(q.ResourceShort.As(q.Resource.Short.Name()).Expire.Lte(*req.ExpireBefore))
|
||||
}
|
||||
|
||||
resource, err := q.Resource.Debug().Where(do).
|
||||
@@ -124,7 +123,7 @@ func ListResourceLong(c *fiber.Ctx) error {
|
||||
// 查询套餐列表
|
||||
do := q.Resource.Where(
|
||||
q.Resource.UserID.Eq(authCtx.User.ID),
|
||||
q.Resource.Type.Eq(int32(resource2.TypeLong)),
|
||||
q.Resource.Type.Eq(int(m.ResourceTypeLong)),
|
||||
)
|
||||
if req.ResourceNo != nil && *req.ResourceNo != "" {
|
||||
do.Where(q.Resource.ResourceNo.Eq(*req.ResourceNo))
|
||||
@@ -133,19 +132,19 @@ func ListResourceLong(c *fiber.Ctx) error {
|
||||
do.Where(q.Resource.Active.Is(*req.Active))
|
||||
}
|
||||
if req.Type != nil {
|
||||
do.Where(q.ResourceLong.As(q.Resource.Long.Name()).Type.Eq(int32(*req.Type)))
|
||||
do.Where(q.ResourceLong.As(q.Resource.Long.Name()).Type.Eq(int(*req.Type)))
|
||||
}
|
||||
if req.CreateAfter != nil {
|
||||
do.Where(q.Resource.CreatedAt.Gte(orm.LocalDateTime(*req.CreateAfter)))
|
||||
do.Where(q.Resource.CreatedAt.Gte(*req.CreateAfter))
|
||||
}
|
||||
if req.CreateBefore != nil {
|
||||
do.Where(q.Resource.CreatedAt.Lte(orm.LocalDateTime(*req.CreateBefore)))
|
||||
do.Where(q.Resource.CreatedAt.Lte(*req.CreateBefore))
|
||||
}
|
||||
if req.ExpireAfter != nil {
|
||||
do.Where(q.ResourceLong.As(q.Resource.Long.Name()).Expire.Gte(orm.LocalDateTime(*req.ExpireAfter)))
|
||||
do.Where(q.ResourceLong.As(q.Resource.Long.Name()).Expire.Gte(*req.ExpireAfter))
|
||||
}
|
||||
if req.ExpireBefore != nil {
|
||||
do.Where(q.ResourceLong.As(q.Resource.Long.Name()).Expire.Lte(orm.LocalDateTime(*req.ExpireBefore)))
|
||||
do.Where(q.ResourceLong.As(q.Resource.Long.Name()).Expire.Lte(*req.ExpireBefore))
|
||||
}
|
||||
|
||||
resource, err := q.Resource.Debug().Where(do).
|
||||
@@ -202,27 +201,27 @@ func AllActiveResource(c *fiber.Ctx) error {
|
||||
q.Resource.UserID.Eq(authCtx.User.ID),
|
||||
q.Resource.Active.Is(true),
|
||||
q.Resource.Where(
|
||||
q.Resource.Type.Eq(int32(resource2.TypeShort)),
|
||||
q.Resource.Type.Eq(int(m.ResourceTypeShort)),
|
||||
q.ResourceShort.As(q.Resource.Short.Name()).Where(
|
||||
short.Type.Eq(int32(resource2.ModeTime)),
|
||||
short.Expire.Gte(orm.LocalDateTime(now)),
|
||||
short.Type.Eq(int(m.ResourceModeTime)),
|
||||
short.Expire.Gte(now),
|
||||
q.ResourceShort.As(q.Resource.Short.Name()).
|
||||
Where(short.DailyLast.Lt(orm.LocalDateTime(u.Today()))).
|
||||
Where(short.DailyLast.Lt(u.Today())).
|
||||
Or(short.DailyLimit.GtCol(short.DailyUsed)),
|
||||
).Or(
|
||||
short.Type.Eq(int32(resource2.ModeCount)),
|
||||
short.Type.Eq(int(m.ResourceModeQuota)),
|
||||
short.Quota.GtCol(short.Used),
|
||||
),
|
||||
).Or(
|
||||
q.Resource.Type.Eq(int32(resource2.TypeLong)),
|
||||
q.Resource.Type.Eq(int(m.ResourceTypeLong)),
|
||||
q.ResourceLong.As(q.Resource.Long.Name()).Where(
|
||||
long.Type.Eq(int32(resource2.ModeTime)),
|
||||
long.Expire.Gte(orm.LocalDateTime(now)),
|
||||
long.Type.Eq(int(m.ResourceModeTime)),
|
||||
long.Expire.Gte(now),
|
||||
q.ResourceLong.As(q.Resource.Long.Name()).
|
||||
Where(long.DailyLast.Lt(orm.LocalDateTime(u.Today()))).
|
||||
Where(long.DailyLast.Lt(u.Today())).
|
||||
Or(long.DailyLimit.GtCol(long.DailyUsed)),
|
||||
).Or(
|
||||
long.Type.Eq(int32(resource2.ModeCount)),
|
||||
long.Type.Eq(int(m.ResourceModeQuota)),
|
||||
long.Quota.GtCol(long.Used),
|
||||
),
|
||||
),
|
||||
@@ -282,23 +281,23 @@ func StatisticResourceFree(c *fiber.Ctx) error {
|
||||
switch {
|
||||
|
||||
// 短效包量
|
||||
case resource2.Type(resource.Type) == resource2.TypeShort && resource2.Mode(resource.Short.Type) == resource2.ModeCount:
|
||||
case resource.Type == m.ResourceTypeShort && resource.Short.Type == m.ResourceModeQuota:
|
||||
if u.Z(resource.Short.Quota) > resource.Short.Used {
|
||||
shortCount++
|
||||
shortQuotaSum += int(u.Z(resource.Short.Quota) - resource.Short.Used)
|
||||
}
|
||||
|
||||
// 长效包量
|
||||
case resource2.Type(resource.Type) == resource2.TypeLong && resource2.Mode(resource.Long.Type) == resource2.ModeCount:
|
||||
case resource.Type == m.ResourceTypeLong && resource.Long.Type == m.ResourceModeQuota:
|
||||
if u.Z(resource.Long.Quota) > resource.Long.Used {
|
||||
longCount++
|
||||
longQuotaSum += int(u.Z(resource.Long.Quota) - resource.Long.Used)
|
||||
}
|
||||
|
||||
// 短效包时
|
||||
case resource2.Type(resource.Type) == resource2.TypeShort && resource2.Mode(resource.Short.Type) == resource2.ModeTime:
|
||||
case resource.Type == m.ResourceTypeShort && resource.Short.Type == m.ResourceModeTime:
|
||||
if time.Time(*resource.Short.Expire).After(time.Now()) {
|
||||
if resource.Short.DailyLast == nil || u.SameDate(time.Time(*resource.Short.DailyLast)) == false {
|
||||
if resource.Short.DailyLast == nil || u.IsToday(time.Time(*resource.Short.DailyLast)) == false {
|
||||
shortCount++
|
||||
shortDailyFreeSum += int(resource.Short.DailyLimit)
|
||||
} else if resource.Short.DailyLimit > resource.Short.DailyUsed {
|
||||
@@ -308,9 +307,9 @@ func StatisticResourceFree(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// 长效包时
|
||||
case resource2.Type(resource.Type) == resource2.TypeLong && resource2.Mode(resource.Long.Type) == resource2.ModeTime:
|
||||
case resource.Type == m.ResourceTypeLong && resource.Long.Type == m.ResourceModeTime:
|
||||
if time.Time(*resource.Long.Expire).After(time.Now()) {
|
||||
if resource.Long.DailyLast == nil || u.SameDate(time.Time(*resource.Long.DailyLast)) == false {
|
||||
if resource.Long.DailyLast == nil || u.IsToday(time.Time(*resource.Long.DailyLast)) == false {
|
||||
longCount++
|
||||
longDailyFreeSum += int(resource.Long.DailyLimit)
|
||||
} else if resource.Long.DailyLimit > resource.Long.DailyUsed {
|
||||
@@ -376,10 +375,10 @@ func StatisticResourceUsage(c *fiber.Ctx) error {
|
||||
do.Where(q.LogsUserUsage.ResourceID.Eq(resourceID))
|
||||
}
|
||||
if req.TimeAfter != nil {
|
||||
do.Where(q.LogsUserUsage.Time.Gte(orm.LocalDateTime(*req.TimeAfter)))
|
||||
do.Where(q.LogsUserUsage.Time.Gte(*req.TimeAfter))
|
||||
}
|
||||
if req.TimeBefore != nil {
|
||||
do.Where(q.LogsUserUsage.Time.Lte(orm.LocalDateTime(*req.TimeBefore)))
|
||||
do.Where(q.LogsUserUsage.Time.Lte(*req.TimeBefore))
|
||||
}
|
||||
|
||||
var data = new(StatisticResourceUsageResp)
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"log/slog"
|
||||
"platform/web/auth"
|
||||
"platform/web/core"
|
||||
trade2 "platform/web/domains/trade"
|
||||
g "platform/web/globals"
|
||||
m "platform/web/models"
|
||||
s "platform/web/services"
|
||||
"time"
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
|
||||
type TradeCreateReq struct {
|
||||
s.CreateTradeData
|
||||
Type trade2.Type `json:"type" validate:"required"`
|
||||
Type m.TradeType `json:"type" validate:"required"`
|
||||
Resource *s.CreateResourceData `json:"resource,omitempty"`
|
||||
Recharge *s.RechargeProductInfo `json:"recharge,omitempty"`
|
||||
}
|
||||
@@ -38,12 +38,12 @@ func TradeCreate(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
switch req.Type {
|
||||
case trade2.TypePurchase:
|
||||
case m.TradeTypePurchase:
|
||||
if req.Resource == nil {
|
||||
return core.NewBizErr("购买信息不能为空")
|
||||
}
|
||||
req.Product = req.Resource
|
||||
case trade2.TypeRecharge:
|
||||
case m.TradeTypeRecharge:
|
||||
if req.Recharge == nil {
|
||||
return core.NewBizErr("充值信息不能为空")
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ type VerifierReq struct {
|
||||
|
||||
func SmsCode(c *fiber.Ctx) error {
|
||||
|
||||
_, err := auth.GetAuthCtx(c).PermitInternalClient()
|
||||
_, err := auth.GetAuthCtx(c).PermitOfficialClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net"
|
||||
"platform/pkg/env"
|
||||
"platform/pkg/u"
|
||||
"platform/web/auth"
|
||||
"platform/web/core"
|
||||
g "platform/web/globals"
|
||||
"platform/web/globals/orm"
|
||||
m "platform/web/models"
|
||||
q "platform/web/queries"
|
||||
"time"
|
||||
@@ -89,7 +90,7 @@ func CreateWhitelist(c *fiber.Ctx) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = secureAddr(req.Host)
|
||||
ip, err := secureAddr(req.Host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -97,7 +98,7 @@ func CreateWhitelist(c *fiber.Ctx) error {
|
||||
// 创建白名单
|
||||
err = q.Whitelist.Create(&m.Whitelist{
|
||||
UserID: authCtx.User.ID,
|
||||
Host: req.Host,
|
||||
IP: u.Z(ip),
|
||||
Remark: &req.Remark,
|
||||
})
|
||||
return nil
|
||||
@@ -125,17 +126,21 @@ func UpdateWhitelist(c *fiber.Ctx) error {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "id is required")
|
||||
}
|
||||
|
||||
ip, err := secureAddr(req.Host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 更新白名单
|
||||
_, err = q.Whitelist.
|
||||
Where(
|
||||
q.Whitelist.ID.Eq(req.ID),
|
||||
q.Whitelist.UserID.Eq(authCtx.User.ID),
|
||||
).
|
||||
Updates(&m.Whitelist{
|
||||
ID: req.ID,
|
||||
Host: req.Host,
|
||||
Remark: &req.Remark,
|
||||
})
|
||||
UpdateSimple(
|
||||
q.Whitelist.IP.Value(ip),
|
||||
q.Whitelist.Remark.Value(req.Remark),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -186,13 +191,13 @@ func RemoveWhitelist(c *fiber.Ctx) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func secureAddr(str string) error {
|
||||
var addr = net.ParseIP(str)
|
||||
if addr == nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "IP 解析失败")
|
||||
func secureAddr(str string) (*orm.Inet, error) {
|
||||
ip, err := orm.ParseInet(str)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if env.RunMode == env.RunModeDev || addr.IsGlobalUnicast() {
|
||||
return nil
|
||||
if !ip.IsGlobalUnicast() && env.RunMode != env.RunModeDev {
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, "IP 地址不可用")
|
||||
}
|
||||
return fiber.NewError(fiber.StatusBadRequest, "IP 地址不可用")
|
||||
return ip, nil
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameAdmin = "admin"
|
||||
|
||||
// Admin mapped from table <admin>
|
||||
type Admin struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:管理员ID" json:"id"` // 管理员ID
|
||||
Username string `gorm:"column:username;type:character varying(255);not null;comment:用户名" json:"username"` // 用户名
|
||||
Password string `gorm:"column:password;type:character varying(255);not null;comment:密码" json:"password"` // 密码
|
||||
Name *string `gorm:"column:name;type:character varying(255);comment:真实姓名" json:"name"` // 真实姓名
|
||||
Avatar *string `gorm:"column:avatar;type:character varying(255);comment:头像URL" json:"avatar"` // 头像URL
|
||||
Phone *string `gorm:"column:phone;type:character varying(255);comment:手机号码" json:"phone"` // 手机号码
|
||||
Email *string `gorm:"column:email;type:character varying(255);comment:邮箱" json:"email"` // 邮箱
|
||||
Status int32 `gorm:"column:status;type:integer;not null;default:1;comment:状态:0-禁用,1-正常" json:"status"` // 状态:0-禁用,1-正常
|
||||
LastLogin *orm.LocalDateTime `gorm:"column:last_login;type:timestamp without time zone;comment:最后登录时间" json:"last_login"` // 最后登录时间
|
||||
LastLoginHost *string `gorm:"column:last_login_host;type:character varying(45);comment:最后登录地址" json:"last_login_host"` // 最后登录地址
|
||||
LastLoginAgent *string `gorm:"column:last_login_agent;type:character varying(255);comment:最后登录代理" json:"last_login_agent"` // 最后登录代理
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName Admin's table name
|
||||
func (*Admin) TableName() string {
|
||||
return TableNameAdmin
|
||||
}
|
||||
31
web/models/admin.go
Normal file
31
web/models/admin.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"platform/web/core"
|
||||
"platform/web/globals/orm"
|
||||
)
|
||||
|
||||
// Admin 管理员表
|
||||
type Admin struct {
|
||||
core.Model
|
||||
Username string `json:"username" gorm:"column:username"` // 用户名
|
||||
Password string `json:"password" gorm:"column:password"` // 密码
|
||||
Name *string `json:"name" gorm:"column:name"` // 真实姓名
|
||||
Avatar *string `json:"avatar" gorm:"column:avatar"` // 头像URL
|
||||
Phone *string `json:"phone" gorm:"column:phone"` // 手机号码
|
||||
Email *string `json:"email" gorm:"column:email"` // 邮箱
|
||||
Status AdminStatus `json:"status" gorm:"column:status"` // 状态:0-禁用,1-正常
|
||||
LastLogin *time.Time `json:"last_login" gorm:"column:last_login"` // 最后登录时间
|
||||
LastLoginIP *orm.Inet `json:"last_login_ip" gorm:"column:last_login_ip"` // 最后登录地址
|
||||
LastLoginUA *string `json:"last_login_ua" gorm:"column:last_login_ua"` // 最后登录代理
|
||||
}
|
||||
|
||||
// AdminStatus 管理员状态枚举
|
||||
type AdminStatus int
|
||||
|
||||
const (
|
||||
AdminStatusDisabled AdminStatus = 0 // 禁用
|
||||
AdminStatusEnabled AdminStatus = 1 // 正常
|
||||
)
|
||||
@@ -1,30 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameAdminRole = "admin_role"
|
||||
|
||||
// AdminRole mapped from table <admin_role>
|
||||
type AdminRole struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:管理员角色ID" json:"id"` // 管理员角色ID
|
||||
Name string `gorm:"column:name;type:character varying(255);not null;comment:角色名称" json:"name"` // 角色名称
|
||||
Description *string `gorm:"column:description;type:character varying(255);comment:角色描述" json:"description"` // 角色描述
|
||||
Active *bool `gorm:"column:active;type:boolean;default:true;comment:是否激活" json:"active"` // 是否激活
|
||||
Sort *int32 `gorm:"column:sort;type:integer;comment:排序" json:"sort"` // 排序
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName AdminRole's table name
|
||||
func (*AdminRole) TableName() string {
|
||||
return TableNameAdminRole
|
||||
}
|
||||
14
web/models/admin_role.go
Normal file
14
web/models/admin_role.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/core"
|
||||
)
|
||||
|
||||
// AdminRole 管理员角色表
|
||||
type AdminRole struct {
|
||||
core.Model
|
||||
Name string `json:"name" gorm:"column:name"` // 角色名称
|
||||
Description *string `json:"description" gorm:"column:description"` // 角色描述
|
||||
Active bool `json:"active" gorm:"column:active"` // 是否激活
|
||||
Sort int32 `json:"sort" gorm:"column:sort"` // 排序
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameAdminRoleLink = "admin_role_link"
|
||||
|
||||
// AdminRoleLink mapped from table <admin_role_link>
|
||||
type AdminRoleLink struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID
|
||||
AdminID int32 `gorm:"column:admin_id;type:integer;not null;comment:管理员ID" json:"admin_id"` // 管理员ID
|
||||
RoleID int32 `gorm:"column:role_id;type:integer;not null;comment:角色ID" json:"role_id"` // 角色ID
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName AdminRoleLink's table name
|
||||
func (*AdminRoleLink) TableName() string {
|
||||
return TableNameAdminRoleLink
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameAdminRolePermissionLink = "admin_role_permission_link"
|
||||
|
||||
// AdminRolePermissionLink mapped from table <admin_role_permission_link>
|
||||
type AdminRolePermissionLink struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID
|
||||
RoleID int32 `gorm:"column:role_id;type:integer;not null;comment:角色ID" json:"role_id"` // 角色ID
|
||||
PermissionID int32 `gorm:"column:permission_id;type:integer;not null;comment:权限ID" json:"permission_id"` // 权限ID
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName AdminRolePermissionLink's table name
|
||||
func (*AdminRolePermissionLink) TableName() string {
|
||||
return TableNameAdminRolePermissionLink
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameAnnouncement = "announcement"
|
||||
|
||||
// Announcement mapped from table <announcement>
|
||||
type Announcement struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:公告ID" json:"id"` // 公告ID
|
||||
Title string `gorm:"column:title;type:character varying(255);not null;comment:公告标题" json:"title"` // 公告标题
|
||||
Content *string `gorm:"column:content;type:text;comment:公告内容" json:"content"` // 公告内容
|
||||
Type int32 `gorm:"column:type;type:integer;not null;default:1;comment:公告类型:1-普通公告" json:"type"` // 公告类型:1-普通公告
|
||||
Pin bool `gorm:"column:pin;type:boolean;not null;comment:是否置顶" json:"pin"` // 是否置顶
|
||||
Status int32 `gorm:"column:status;type:integer;not null;default:1;comment:公告状态:0-禁用,1-正常" json:"status"` // 公告状态:0-禁用,1-正常
|
||||
Sort int32 `gorm:"column:sort;type:integer;not null;comment:公告排序" json:"sort"` // 公告排序
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName Announcement's table name
|
||||
func (*Announcement) TableName() string {
|
||||
return TableNameAnnouncement
|
||||
}
|
||||
31
web/models/announcement.go
Normal file
31
web/models/announcement.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/core"
|
||||
)
|
||||
|
||||
// Announcement 公告表
|
||||
type Announcement struct {
|
||||
core.Model
|
||||
Title string `json:"title" gorm:"column:title"` // 公告标题
|
||||
Content *string `json:"content" gorm:"column:content"` // 公告内容
|
||||
Type AnnouncementType `json:"type" gorm:"column:type"` // 公告类型:1-普通公告
|
||||
Pin bool `json:"pin" gorm:"column:pin"` // 是否置顶
|
||||
Status AnnouncementStatus `json:"status" gorm:"column:status"` // 公告状态:0-禁用,1-正常
|
||||
Sort int32 `json:"sort" gorm:"column:sort"` // 公告排序
|
||||
}
|
||||
|
||||
// AnnouncementType 公告类型枚举
|
||||
type AnnouncementType int
|
||||
|
||||
const (
|
||||
AnnouncementTypeNormal AnnouncementType = 1 // 普通公告
|
||||
)
|
||||
|
||||
// AnnouncementStatus 公告状态枚举
|
||||
type AnnouncementStatus int
|
||||
|
||||
const (
|
||||
AnnouncementStatusDisabled AnnouncementStatus = 0 // 禁用
|
||||
AnnouncementStatusEnabled AnnouncementStatus = 1 // 正常
|
||||
)
|
||||
@@ -1,38 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameBill = "bill"
|
||||
|
||||
// Bill mapped from table <bill>
|
||||
type Bill struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:账单ID" json:"id"` // 账单ID
|
||||
UserID int32 `gorm:"column:user_id;type:integer;not null;comment:用户ID" json:"user_id"` // 用户ID
|
||||
TradeID *int32 `gorm:"column:trade_id;type:integer;comment:订单ID" json:"trade_id"` // 订单ID
|
||||
ResourceID *int32 `gorm:"column:resource_id;type:integer;comment:套餐ID" json:"resource_id"` // 套餐ID
|
||||
RefundID *int32 `gorm:"column:refund_id;type:integer;comment:退款ID" json:"refund_id"` // 退款ID
|
||||
BillNo string `gorm:"column:bill_no;type:character varying(255);not null;comment:易读账单号" json:"bill_no"` // 易读账单号
|
||||
Info *string `gorm:"column:info;type:character varying(255);comment:产品可读信息" json:"info"` // 产品可读信息
|
||||
Type int32 `gorm:"column:type;type:integer;not null;comment:账单类型:1-消费,2-退款,3-充值" json:"type"` // 账单类型:1-消费,2-退款,3-充值
|
||||
Amount decimal.Decimal `gorm:"column:amount;type:numeric(12,2);not null;comment:账单金额" json:"amount"` // 账单金额
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
Trade *Trade `gorm:"foreignKey:TradeID" json:"trade"`
|
||||
Refund *Refund `gorm:"foreignKey:RefundID" json:"refund"`
|
||||
Resource *Resource `gorm:"foreignKey:ResourceID" json:"resource"`
|
||||
}
|
||||
|
||||
// TableName Bill's table name
|
||||
func (*Bill) TableName() string {
|
||||
return TableNameBill
|
||||
}
|
||||
34
web/models/bill.go
Normal file
34
web/models/bill.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/core"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
// Bill 账单表
|
||||
type Bill struct {
|
||||
core.Model
|
||||
UserID int32 `json:"user_id" gorm:"column:user_id"` // 用户ID
|
||||
TradeID *int32 `json:"trade_id" gorm:"column:trade_id"` // 订单ID
|
||||
ResourceID *int32 `json:"resource_id" gorm:"column:resource_id"` // 套餐ID
|
||||
RefundID *int32 `json:"refund_id" gorm:"column:refund_id"` // 退款ID
|
||||
BillNo string `json:"bill_no" gorm:"column:bill_no"` // 易读账单号
|
||||
Info *string `json:"info" gorm:"column:info"` // 产品可读信息
|
||||
Type BillType `json:"type" gorm:"column:type"` // 账单类型:1-消费,2-退款,3-充值
|
||||
Amount decimal.Decimal `json:"amount" gorm:"column:amount"` // 账单金额
|
||||
|
||||
User *User `json:"user" gorm:"foreignKey:UserID"`
|
||||
Trade *Trade `json:"trade" gorm:"foreignKey:TradeID"`
|
||||
Resource *Resource `json:"resource" gorm:"foreignKey:ResourceID"`
|
||||
Refund *Refund `json:"refund" gorm:"foreignKey:RefundID"`
|
||||
}
|
||||
|
||||
// BillType 账单类型枚举
|
||||
type BillType int
|
||||
|
||||
const (
|
||||
BillTypeConsume BillType = 1 // 消费
|
||||
BillTypeRefund BillType = 2 // 退款
|
||||
BillTypeRecharge BillType = 3 // 充值
|
||||
)
|
||||
@@ -1,40 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameChannel = "channel"
|
||||
|
||||
// Channel mapped from table <channel>
|
||||
type Channel struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:通道ID" json:"id"` // 通道ID
|
||||
UserID int32 `gorm:"column:user_id;type:integer;not null;comment:用户ID" json:"user_id"` // 用户ID
|
||||
ProxyID int32 `gorm:"column:proxy_id;type:integer;not null;comment:代理ID" json:"proxy_id"` // 代理ID
|
||||
EdgeID *int32 `gorm:"column:edge_id;type:integer;comment:节点ID" json:"edge_id"` // 节点ID
|
||||
ResourceID int32 `gorm:"column:resource_id;type:integer;not null;comment:套餐ID" json:"resource_id"` // 套餐ID
|
||||
ProxyHost string `gorm:"column:proxy_host;type:character varying(255);not null;comment:代理地址" json:"proxy_host"` // 代理地址
|
||||
ProxyPort int32 `gorm:"column:proxy_port;type:integer;not null;comment:转发端口" json:"proxy_port"` // 转发端口
|
||||
EdgeHost *string `gorm:"column:edge_host;type:character varying(255);comment:节点地址" json:"edge_host"` // 节点地址
|
||||
Protocol *int32 `gorm:"column:protocol;type:integer;comment:协议类型:1-http,2-https,3-socks5" json:"protocol"` // 协议类型:1-http,2-https,3-socks5
|
||||
AuthIP bool `gorm:"column:auth_ip;type:boolean;not null;comment:IP认证" json:"auth_ip"` // IP认证
|
||||
Whitelists *string `gorm:"column:whitelists;type:text;comment:IP白名单,逗号分隔" json:"whitelists"` // IP白名单,逗号分隔
|
||||
AuthPass bool `gorm:"column:auth_pass;type:boolean;not null;comment:密码认证" json:"auth_pass"` // 密码认证
|
||||
Username *string `gorm:"column:username;type:character varying(255);comment:用户名" json:"username"` // 用户名
|
||||
Password *string `gorm:"column:password;type:character varying(255);comment:密码" json:"password"` // 密码
|
||||
Expiration orm.LocalDateTime `gorm:"column:expiration;type:timestamp without time zone;not null;comment:过期时间" json:"expiration"` // 过期时间
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName Channel's table name
|
||||
func (*Channel) TableName() string {
|
||||
return TableNameChannel
|
||||
}
|
||||
31
web/models/channel.go
Normal file
31
web/models/channel.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/core"
|
||||
"platform/web/globals/orm"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Channel 通道表
|
||||
type Channel struct {
|
||||
core.Model
|
||||
UserID int32 `json:"user_id" gorm:"column:user_id"` // 用户ID
|
||||
ResourceID int32 `json:"resource_id" gorm:"column:resource_id"` // 套餐ID
|
||||
ProxyID int32 `json:"proxy_id" gorm:"column:proxy_id"` // 代理ID
|
||||
BatchNo string `json:"batch_no" gorm:"column:batch_no"` // 批次编号
|
||||
Port uint16 `json:"port" gorm:"column:port"` // 代理端口
|
||||
EdgeID *int32 `json:"edge_id" gorm:"column:edge_id"` // 节点ID(手动配置)
|
||||
FilterISP *EdgeISP `json:"filter_isp" gorm:"column:filter_isp"` // 运营商过滤(自动配置):参考 edge.isp
|
||||
FilterProv *string `json:"filter_prov" gorm:"column:filter_prov"` // 省份过滤(自动配置)
|
||||
FilterCity *string `json:"filter_city" gorm:"column:filter_city"` // 城市过滤(自动配置)
|
||||
IP *orm.Inet `json:"ip" gorm:"column:ip"` // 节点地址
|
||||
Whitelists *orm.Slice[string] `json:"whitelists" gorm:"column:whitelists"` // IP白名单,逗号分隔
|
||||
Username *string `json:"username" gorm:"column:username"` // 用户名
|
||||
Password *string `json:"password" gorm:"column:password"` // 密码
|
||||
ExpiredAt time.Time `json:"expired_at" gorm:"column:expired_at"` // 过期时间
|
||||
|
||||
User User `json:"user" gorm:"foreignKey:UserID"`
|
||||
Resource Resource `json:"resource" gorm:"foreignKey:ResourceID"`
|
||||
Proxy Proxy `json:"proxy" gorm:"foreignKey:ProxyID"`
|
||||
Edge *Edge `json:"edge" gorm:"foreignKey:EdgeID"`
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameClient = "client"
|
||||
|
||||
// Client mapped from table <client>
|
||||
type Client struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:客户端ID" json:"id"` // 客户端ID
|
||||
ClientID string `gorm:"column:client_id;type:character varying(255);not null;comment:OAuth2客户端标识符" json:"client_id"` // OAuth2客户端标识符
|
||||
ClientSecret string `gorm:"column:client_secret;type:character varying(255);not null;comment:OAuth2客户端密钥" json:"client_secret"` // OAuth2客户端密钥
|
||||
RedirectURI *string `gorm:"column:redirect_uri;type:character varying(255);comment:OAuth2 重定向URI" json:"redirect_uri"` // OAuth2 重定向URI
|
||||
Spec int32 `gorm:"column:spec;type:integer;not null;comment:安全规范:1-native,2-browser,3-web,4-api" json:"spec"` // 安全规范:1-native,2-browser,3-web,4-api
|
||||
Name string `gorm:"column:name;type:character varying(255);not null;comment:名称" json:"name"` // 名称
|
||||
Icon *string `gorm:"column:icon;type:character varying(255);comment:图标URL" json:"icon"` // 图标URL
|
||||
Status int32 `gorm:"column:status;type:integer;not null;default:1;comment:状态:0-禁用,1-正常" json:"status"` // 状态:0-禁用,1-正常
|
||||
Type int32 `gorm:"column:type;type:integer;not null;comment:类型:0-普通,1-官方" json:"type"` // 类型:0-普通,1-官方
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName Client's table name
|
||||
func (*Client) TableName() string {
|
||||
return TableNameClient
|
||||
}
|
||||
44
web/models/client.go
Normal file
44
web/models/client.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/core"
|
||||
)
|
||||
|
||||
// Client 客户端表
|
||||
type Client struct {
|
||||
core.Model
|
||||
ClientID string `json:"client_id" gorm:"column:client_id"` // OAuth2客户端标识符
|
||||
ClientSecret string `json:"client_secret" gorm:"column:client_secret"` // OAuth2客户端密钥
|
||||
RedirectURI *string `json:"redirect_uri" gorm:"column:redirect_uri"` // OAuth2 重定向URI
|
||||
Spec ClientSpec `json:"spec" gorm:"column:spec"` // 安全规范:1-native,2-browser,3-web,4-api
|
||||
Name string `json:"name" gorm:"column:name"` // 名称
|
||||
Icon *string `json:"icon" gorm:"column:icon"` // 图标URL
|
||||
Status ClientStatus `json:"status" gorm:"column:status"` // 状态:0-禁用,1-正常
|
||||
Type ClientType `json:"type" gorm:"column:type"` // 类型:0-普通,1-官方
|
||||
}
|
||||
|
||||
// ClientSpec 客户端安全规范枚举
|
||||
type ClientSpec int
|
||||
|
||||
const (
|
||||
ClientSpecNative ClientSpec = 1 // native
|
||||
ClientSpecBrowser ClientSpec = 2 // browser
|
||||
ClientSpecWeb ClientSpec = 3 // web
|
||||
ClientSpecAPI ClientSpec = 4 // api
|
||||
)
|
||||
|
||||
// ClientStatus 客户端状态枚举
|
||||
type ClientStatus int
|
||||
|
||||
const (
|
||||
ClientStatusDisabled ClientStatus = 0 // 禁用
|
||||
ClientStatusEnabled ClientStatus = 1 // 正常
|
||||
)
|
||||
|
||||
// ClientType 客户端类型枚举
|
||||
type ClientType int
|
||||
|
||||
const (
|
||||
ClientTypeNormal ClientType = 0 // 普通
|
||||
ClientTypeOfficial ClientType = 1 // 官方
|
||||
)
|
||||
@@ -1,28 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameClientPermissionLink = "client_permission_link"
|
||||
|
||||
// ClientPermissionLink mapped from table <client_permission_link>
|
||||
type ClientPermissionLink struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID
|
||||
ClientID int32 `gorm:"column:client_id;type:integer;not null;comment:客户端ID" json:"client_id"` // 客户端ID
|
||||
PermissionID int32 `gorm:"column:permission_id;type:integer;not null;comment:权限ID" json:"permission_id"` // 权限ID
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName ClientPermissionLink's table name
|
||||
func (*ClientPermissionLink) TableName() string {
|
||||
return TableNameClientPermissionLink
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameCoupon = "coupon"
|
||||
|
||||
// Coupon mapped from table <coupon>
|
||||
type Coupon struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:优惠券ID" json:"id"` // 优惠券ID
|
||||
UserID *int32 `gorm:"column:user_id;type:integer;comment:用户ID" json:"user_id"` // 用户ID
|
||||
Code string `gorm:"column:code;type:character varying(255);not null;comment:优惠券代码" json:"code"` // 优惠券代码
|
||||
Remark *string `gorm:"column:remark;type:character varying(255);comment:优惠券备注" json:"remark"` // 优惠券备注
|
||||
Amount decimal.Decimal `gorm:"column:amount;type:numeric(12,2);not null;comment:优惠券金额" json:"amount"` // 优惠券金额
|
||||
MinAmount decimal.Decimal `gorm:"column:min_amount;type:numeric(12,2);not null;comment:最低消费金额" json:"min_amount"` // 最低消费金额
|
||||
Status int32 `gorm:"column:status;type:integer;not null;comment:优惠券状态:0-未使用,1-已使用,2-已过期" json:"status"` // 优惠券状态:0-未使用,1-已使用,2-已过期
|
||||
ExpireAt *orm.LocalDateTime `gorm:"column:expire_at;type:timestamp without time zone;comment:过期时间" json:"expire_at"` // 过期时间
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName Coupon's table name
|
||||
func (*Coupon) TableName() string {
|
||||
return TableNameCoupon
|
||||
}
|
||||
29
web/models/coupon.go
Normal file
29
web/models/coupon.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/core"
|
||||
"time"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
// Coupon 优惠券表
|
||||
type Coupon struct {
|
||||
core.Model
|
||||
UserID *int32 `json:"user_id" gorm:"column:user_id"` // 用户ID
|
||||
Code string `json:"code" gorm:"column:code"` // 优惠券代码
|
||||
Remark *string `json:"remark" gorm:"column:remark"` // 优惠券备注
|
||||
Amount decimal.Decimal `json:"amount" gorm:"column:amount"` // 优惠券金额
|
||||
MinAmount decimal.Decimal `json:"min_amount" gorm:"column:min_amount"` // 最低消费金额
|
||||
Status CouponStatus `json:"status" gorm:"column:status"` // 优惠券状态:0-未使用,1-已使用,2-已过期
|
||||
ExpireAt *time.Time `json:"expire_at" gorm:"column:expire_at"` // 过期时间
|
||||
}
|
||||
|
||||
// CouponStatus 优惠券状态枚举
|
||||
type CouponStatus int
|
||||
|
||||
const (
|
||||
CouponStatusUnused CouponStatus = 0 // 未使用
|
||||
CouponStatusUsed CouponStatus = 1 // 已使用
|
||||
CouponStatusExpired CouponStatus = 2 // 已过期
|
||||
)
|
||||
@@ -1,38 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameEdge = "edge"
|
||||
|
||||
// Edge mapped from table <edge>
|
||||
type Edge struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:节点ID" json:"id"` // 节点ID
|
||||
ProxyID *int32 `gorm:"column:proxy_id;type:integer;comment:代理ID" json:"proxy_id"` // 代理ID
|
||||
Type int32 `gorm:"column:type;type:integer;not null;comment:节点类型:1-自建" json:"type"` // 节点类型:1-自建
|
||||
Version int32 `gorm:"column:version;type:integer;not null;comment:节点版本" json:"version"` // 节点版本
|
||||
Name string `gorm:"column:name;type:character varying(255);not null;comment:节点名称" json:"name"` // 节点名称
|
||||
Host string `gorm:"column:host;type:character varying(255);not null;comment:节点地址" json:"host"` // 节点地址
|
||||
Isp int32 `gorm:"column:isp;type:integer;not null;comment:运营商:0-未知,1-电信,2-联通,3-移动" json:"isp"` // 运营商:0-未知,1-电信,2-联通,3-移动
|
||||
Prov string `gorm:"column:prov;type:character varying(255);not null;comment:省份" json:"prov"` // 省份
|
||||
City string `gorm:"column:city;type:character varying(255);not null;comment:城市" json:"city"` // 城市
|
||||
ProxyPort *int32 `gorm:"column:proxy_port;type:integer;comment:代理端口" json:"proxy_port"` // 代理端口
|
||||
Status int32 `gorm:"column:status;type:integer;not null;comment:节点状态:0-离线,1-正常" json:"status"` // 节点状态:0-离线,1-正常
|
||||
Rtt *int32 `gorm:"column:rtt;type:integer;comment:最近平均延迟" json:"rtt"` // 最近平均延迟
|
||||
Loss *int32 `gorm:"column:loss;type:integer;comment:最近丢包率" json:"loss"` // 最近丢包率
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName Edge's table name
|
||||
func (*Edge) TableName() string {
|
||||
return TableNameEdge
|
||||
}
|
||||
65
web/models/edge.go
Normal file
65
web/models/edge.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/core"
|
||||
"platform/web/globals/orm"
|
||||
)
|
||||
|
||||
// Edge 节点表
|
||||
type Edge struct {
|
||||
core.Model
|
||||
Type EdgeType `json:"type" gorm:"column:type"` // 节点类型:1-自建
|
||||
Version int32 `json:"version" gorm:"column:version"` // 节点版本
|
||||
Mac string `json:"mac" gorm:"column:mac"` // 节点 mac 地址
|
||||
IP orm.Inet `json:"ip" gorm:"column:ip;not null"` // 节点地址
|
||||
ISP EdgeISP `json:"isp" gorm:"column:isp"` // 运营商:0-未知,1-电信,2-联通,3-移动
|
||||
Prov string `json:"prov" gorm:"column:prov"` // 省份
|
||||
City string `json:"city" gorm:"column:city"` // 城市
|
||||
Status EdgeStatus `json:"status" gorm:"column:status"` // 节点状态:0-离线,1-正常
|
||||
RTT int32 `json:"rtt" gorm:"column:rtt"` // 最近平均延迟
|
||||
Loss int32 `json:"loss" gorm:"column:loss"` // 最近丢包率
|
||||
}
|
||||
|
||||
// EdgeType 节点类型枚举
|
||||
type EdgeType int
|
||||
|
||||
const (
|
||||
EdgeTypeSelfBuilt EdgeType = 1 // 自建
|
||||
)
|
||||
|
||||
// EdgeStatus 节点状态枚举
|
||||
type EdgeStatus int
|
||||
|
||||
const (
|
||||
EdgeStatusOffline EdgeStatus = 0 // 离线
|
||||
EdgeStatusNormal EdgeStatus = 1 // 正常
|
||||
)
|
||||
|
||||
// EdgeISP 运营商枚举
|
||||
type EdgeISP int
|
||||
|
||||
const (
|
||||
EdgeISPTelecom EdgeISP = 1 // 电信
|
||||
EdgeISPUnicom EdgeISP = 2 // 联通
|
||||
EdgeISPMobile EdgeISP = 3 // 移动
|
||||
)
|
||||
|
||||
func (isp *EdgeISP) String() string {
|
||||
if isp == nil {
|
||||
return ""
|
||||
}
|
||||
switch *isp {
|
||||
case EdgeISPTelecom:
|
||||
return "电信"
|
||||
case EdgeISPUnicom:
|
||||
return "联通"
|
||||
case EdgeISPMobile:
|
||||
return "移动"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func ToEdgeISP(i int) EdgeISP {
|
||||
return EdgeISP(i)
|
||||
}
|
||||
8
web/models/link_admin_role.go
Normal file
8
web/models/link_admin_role.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package models
|
||||
|
||||
// LinkAdminRole 管理员角色关联表
|
||||
type LinkAdminRole struct {
|
||||
ID int32 `json:"id" gorm:"column:id"` // 关联ID
|
||||
AdminID int32 `json:"admin_id" gorm:"column:admin_id"` // 管理员ID
|
||||
RoleID int32 `json:"role_id" gorm:"column:role_id"` // 角色ID
|
||||
}
|
||||
8
web/models/link_admin_role_permission.go
Normal file
8
web/models/link_admin_role_permission.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package models
|
||||
|
||||
// LinkAdminRolePermission 管理员角色权限关联表
|
||||
type LinkAdminRolePermission struct {
|
||||
ID int32 `json:"id" gorm:"column:id"` // 关联ID
|
||||
RoleID int32 `json:"role_id" gorm:"column:role_id"` // 角色ID
|
||||
PermissionID int32 `json:"permission_id" gorm:"column:permission_id"` // 权限ID
|
||||
}
|
||||
8
web/models/link_client_permission.go
Normal file
8
web/models/link_client_permission.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package models
|
||||
|
||||
// LinkClientPermission 客户端权限关联表
|
||||
type LinkClientPermission struct {
|
||||
ID int32 `json:"id" gorm:"column:id"` // 关联ID
|
||||
ClientID int32 `json:"client_id" gorm:"column:client_id"` // 客户端ID
|
||||
PermissionID int32 `json:"permission_id" gorm:"column:permission_id"` // 权限ID
|
||||
}
|
||||
8
web/models/link_user_role.go
Normal file
8
web/models/link_user_role.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package models
|
||||
|
||||
// LinkUserRole 用户角色关联表
|
||||
type LinkUserRole struct {
|
||||
ID int32 `json:"id" gorm:"column:id"` // 关联ID
|
||||
UserID int32 `json:"user_id" gorm:"column:user_id"` // 用户ID
|
||||
RoleID int32 `json:"role_id" gorm:"column:role_id"` // 角色ID
|
||||
}
|
||||
8
web/models/link_user_role_permission.go
Normal file
8
web/models/link_user_role_permission.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package models
|
||||
|
||||
// LinkUserRolePermission 用户角色权限关联表
|
||||
type LinkUserRolePermission struct {
|
||||
ID int32 `json:"id" gorm:"column:id"` // 关联ID
|
||||
RoleID int32 `json:"role_id" gorm:"column:role_id"` // 角色ID
|
||||
PermissionID int32 `json:"permission_id" gorm:"column:permission_id"` // 权限ID
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import "platform/web/globals/orm"
|
||||
|
||||
const TableNameLogsLogin = "logs_login"
|
||||
|
||||
// LogsLogin mapped from table <logs_login>
|
||||
type LogsLogin struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:登录日志ID" json:"id"` // 登录日志ID
|
||||
IP string `gorm:"column:ip;type:character varying(45);not null;comment:IP地址" json:"ip"` // IP地址
|
||||
UA string `gorm:"column:ua;type:character varying(255);not null;comment:用户代理" json:"ua"` // 用户代理
|
||||
GrantType string `gorm:"column:grant_type;type:character varying(255);not null;comment:授权类型:authorization_code-授权码模式,client_credentials-客户端凭证模式,refresh_token-刷新令牌模式,password-密码模式" json:"grant_type"` // 授权类型:authorization_code-授权码模式,client_credentials-客户端凭证模式,refresh_token-刷新令牌模式,password-密码模式
|
||||
PasswordGrantType string `gorm:"column:password_grant_type;type:character varying(255);not null;comment:密码模式子授权类型:password-账号密码,phone_code-手机验证码,email_code-邮箱验证码" json:"password_grant_type"` // 密码模式子授权类型:password-账号密码,phone_code-手机验证码,email_code-邮箱验证码
|
||||
Success bool `gorm:"column:success;type:boolean;not null;comment:登录是否成功" json:"success"` // 登录是否成功
|
||||
UserID *int32 `gorm:"column:user_id;type:integer;comment:用户ID" json:"user_id"` // 用户ID
|
||||
Time orm.LocalDateTime `gorm:"column:time;type:timestamp without time zone;not null;comment:登录时间" json:"time"` // 登录时间
|
||||
}
|
||||
|
||||
// TableName LogsLogin's table name
|
||||
func (*LogsLogin) TableName() string {
|
||||
return TableNameLogsLogin
|
||||
}
|
||||
39
web/models/logs_login.go
Normal file
39
web/models/logs_login.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
"time"
|
||||
)
|
||||
|
||||
// LogsLogin 登录日志表
|
||||
type LogsLogin struct {
|
||||
ID int32 `json:"id" gorm:"column:id"` // 登录日志ID
|
||||
IP orm.Inet `json:"ip" gorm:"column:ip;not null"` // IP地址
|
||||
UA string `json:"ua" gorm:"column:ua"` // 用户代理
|
||||
GrantType GrantType `json:"grant_type" gorm:"column:grant_type"` // 授权类型
|
||||
PasswordType PasswordType `json:"password_type" gorm:"column:password_type"` // 密码模式子授权类型
|
||||
Success bool `json:"success" gorm:"column:success"` // 登录是否成功
|
||||
UserID *int32 `json:"user_id" gorm:"column:user_id"` // 用户ID
|
||||
Time time.Time `json:"time" gorm:"column:time"` // 登录时间
|
||||
|
||||
User *User `json:"user" gorm:"foreignKey:UserID"`
|
||||
}
|
||||
|
||||
// GrantType 授权类型枚举
|
||||
type GrantType string
|
||||
|
||||
const (
|
||||
GrantTypeAuthorizationCode GrantType = "authorization_code" // 授权码模式
|
||||
GrantTypeClientCredentials GrantType = "client_credentials" // 客户端凭证模式
|
||||
GrantTypeRefreshToken GrantType = "refresh_token" // 刷新令牌模式
|
||||
GrantTypePassword GrantType = "password" // 密码模式
|
||||
)
|
||||
|
||||
// PasswordType 密码模式子授权类型枚举
|
||||
type PasswordType string
|
||||
|
||||
const (
|
||||
PasswordTypePassword PasswordType = "password" // 账号密码
|
||||
PasswordTypePhoneCode PasswordType = "phone_code" // 手机验证码
|
||||
PasswordTypeEmailCode PasswordType = "email_code" // 邮箱验证码
|
||||
)
|
||||
@@ -1,29 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import "platform/web/globals/orm"
|
||||
|
||||
const TableNameLogsRequest = "logs_request"
|
||||
|
||||
// LogsRequest mapped from table <logs_request>
|
||||
type LogsRequest struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:访问日志ID" json:"id"` // 访问日志ID
|
||||
IP string `gorm:"column:ip;type:character varying(45);not null;comment:IP地址" json:"ip"` // IP地址
|
||||
UA string `gorm:"column:ua;type:character varying(255);not null;comment:用户代理" json:"ua"` // 用户代理
|
||||
UserID *int32 `gorm:"column:user_id;type:integer;comment:用户ID" json:"user_id"` // 用户ID
|
||||
ClientID *int32 `gorm:"column:client_id;type:integer;comment:客户端ID" json:"client_id"` // 客户端ID
|
||||
Method string `gorm:"column:method;type:character varying(10);not null;comment:请求方法" json:"method"` // 请求方法
|
||||
Path string `gorm:"column:path;type:character varying(255);not null;comment:请求路径" json:"path"` // 请求路径
|
||||
Status int32 `gorm:"column:status;type:integer;not null;comment:响应状态码" json:"status"` // 响应状态码
|
||||
Error *string `gorm:"column:error;type:text;comment:错误信息" json:"error"` // 错误信息
|
||||
Time orm.LocalDateTime `gorm:"column:time;type:timestamp without time zone;not null;comment:请求时间" json:"time"` // 请求时间
|
||||
Latency string `gorm:"column:latency;type:character varying(255);not null;comment:请求延迟" json:"latency"` // 请求延迟
|
||||
}
|
||||
|
||||
// TableName LogsRequest's table name
|
||||
func (*LogsRequest) TableName() string {
|
||||
return TableNameLogsRequest
|
||||
}
|
||||
24
web/models/logs_request.go
Normal file
24
web/models/logs_request.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
"time"
|
||||
)
|
||||
|
||||
// LogsRequest 访问日志表
|
||||
type LogsRequest struct {
|
||||
ID int32 `json:"id" gorm:"column:id"` // 访问日志ID
|
||||
IP orm.Inet `json:"ip" gorm:"column:ip;not null"` // IP地址
|
||||
UA string `json:"ua" gorm:"column:ua"` // 用户代理
|
||||
UserID *int32 `json:"user_id" gorm:"column:user_id"` // 用户ID
|
||||
ClientID *int32 `json:"client_id" gorm:"column:client_id"` // 客户端ID
|
||||
Method string `json:"method" gorm:"column:method"` // 请求方法
|
||||
Path string `json:"path" gorm:"column:path"` // 请求路径
|
||||
Status int16 `json:"status" gorm:"column:status"` // 响应状态码
|
||||
Error *string `json:"error" gorm:"column:error"` // 错误信息
|
||||
Time time.Time `json:"time" gorm:"column:time"` // 请求时间
|
||||
Latency string `json:"latency" gorm:"column:latency"` // 请求延迟
|
||||
|
||||
User *User `json:"user" gorm:"foreignKey:UserID"`
|
||||
Client *Client `json:"client" gorm:"foreignKey:ClientID"`
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import "platform/web/globals/orm"
|
||||
|
||||
const TableNameLogsUserBandwidth = "logs_user_bandwidth"
|
||||
|
||||
// LogsUserBandwidth mapped from table <logs_user_bandwidth>
|
||||
type LogsUserBandwidth struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:日志ID" json:"id"` // 日志ID
|
||||
UserID int32 `gorm:"column:user_id;type:integer;not null;comment:用户ID" json:"user_id"` // 用户ID
|
||||
Bandwidth int32 `gorm:"column:bandwidth;type:integer;not null;comment:带宽使用量(KB)" json:"bandwidth"` // 带宽使用量(KB)
|
||||
Time orm.LocalDateTime `gorm:"column:time;type:timestamp without time zone;not null;comment:记录时间" json:"time"` // 记录时间
|
||||
}
|
||||
|
||||
// TableName LogsUserBandwidth's table name
|
||||
func (*LogsUserBandwidth) TableName() string {
|
||||
return TableNameLogsUserBandwidth
|
||||
}
|
||||
13
web/models/logs_user_bandwidth.go
Normal file
13
web/models/logs_user_bandwidth.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// LogsUserBandwidth 用户带宽日志表
|
||||
type LogsUserBandwidth struct {
|
||||
ID int32 `json:"id" gorm:"column:id;not null"` // 日志ID
|
||||
UserID int32 `json:"user_id" gorm:"column:user_id"` // 用户ID
|
||||
Bandwidth int32 `json:"bandwidth" gorm:"column:bandwidth"` // 带宽使用量(KB)
|
||||
Time time.Time `json:"time" gorm:"column:time"` // 记录时间
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import "platform/web/globals/orm"
|
||||
|
||||
const TableNameLogsUserUsage = "logs_user_usage"
|
||||
|
||||
// LogsUserUsage mapped from table <logs_user_usage>
|
||||
type LogsUserUsage struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:日志ID" json:"id"` // 日志ID
|
||||
UserID int32 `gorm:"column:user_id;type:integer;not null;comment:用户ID" json:"user_id"` // 用户ID
|
||||
ResourceID int32 `gorm:"column:resource_id;type:integer;not null;comment:套餐ID" json:"resource_id"` // 套餐ID
|
||||
Count_ int32 `gorm:"column:count;type:integer;not null;comment:数量" json:"count"` // 数量
|
||||
Prov *string `gorm:"column:prov;type:character varying(255);comment:省份" json:"prov"` // 省份
|
||||
City *string `gorm:"column:city;type:character varying(255);comment:城市" json:"city"` // 城市
|
||||
Isp *string `gorm:"column:isp;type:character varying(255);comment:运营商" json:"isp"` // 运营商
|
||||
IP string `gorm:"column:ip;type:character varying(45);not null;comment:IP地址" json:"ip"` // IP地址
|
||||
Time orm.LocalDateTime `gorm:"column:time;type:timestamp without time zone;not null;comment:提取时间" json:"time"` // 提取时间
|
||||
}
|
||||
|
||||
// TableName LogsUserUsage's table name
|
||||
func (*LogsUserUsage) TableName() string {
|
||||
return TableNameLogsUserUsage
|
||||
}
|
||||
19
web/models/logs_user_usage.go
Normal file
19
web/models/logs_user_usage.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
"time"
|
||||
)
|
||||
|
||||
// LogsUserUsage 用户使用日志表
|
||||
type LogsUserUsage struct {
|
||||
ID int32 `json:"id" gorm:"column:id"` // 日志ID
|
||||
UserID int32 `json:"user_id" gorm:"column:user_id"` // 用户ID
|
||||
ResourceID int32 `json:"resource_id" gorm:"column:resource_id"` // 套餐ID
|
||||
Count int32 `json:"count" gorm:"column:count"` // 数量
|
||||
Prov *string `json:"prov" gorm:"column:prov"` // 省份
|
||||
City *string `json:"city" gorm:"column:city"` // 城市
|
||||
ISP *string `json:"isp" gorm:"column:isp"` // 运营商
|
||||
IP orm.Inet `json:"ip" gorm:"column:ip"` // IP地址
|
||||
Time time.Time `json:"time" gorm:"column:time"` // 提取时间
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNamePermission = "permission"
|
||||
|
||||
// Permission mapped from table <permission>
|
||||
type Permission struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:权限ID" json:"id"` // 权限ID
|
||||
ParentID *int32 `gorm:"column:parent_id;type:integer;comment:父权限ID" json:"parent_id"` // 父权限ID
|
||||
Name string `gorm:"column:name;type:character varying(255);not null;comment:权限名称" json:"name"` // 权限名称
|
||||
Description *string `gorm:"column:description;type:character varying(255);comment:权限描述" json:"description"` // 权限描述
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName Permission's table name
|
||||
func (*Permission) TableName() string {
|
||||
return TableNamePermission
|
||||
}
|
||||
14
web/models/permission.go
Normal file
14
web/models/permission.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package models
|
||||
|
||||
import "platform/web/core"
|
||||
|
||||
// Permission 权限表
|
||||
type Permission struct {
|
||||
core.Model
|
||||
ParentID *int32 `json:"parent_id" gorm:"column:parent_id"` // 父权限ID
|
||||
Name string `json:"name" gorm:"column:name"` // 权限名称
|
||||
Description *string `json:"description" gorm:"column:description"` // 权限描述
|
||||
|
||||
Parent *Permission `json:"parent" gorm:"foreignKey:ParentID"`
|
||||
Children []*Permission `json:"children" gorm:"foreignKey:ParentID"`
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameProduct = "product"
|
||||
|
||||
// Product mapped from table <product>
|
||||
type Product struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:产品ID" json:"id"` // 产品ID
|
||||
Code string `gorm:"column:code;type:character varying(255);not null;comment:产品代码" json:"code"` // 产品代码
|
||||
Name string `gorm:"column:name;type:character varying(255);not null;comment:产品名称" json:"name"` // 产品名称
|
||||
Description *string `gorm:"column:description;type:character varying(255);comment:产品描述" json:"description"` // 产品描述
|
||||
Sort int32 `gorm:"column:sort;type:integer;not null;comment:排序" json:"sort"` // 排序
|
||||
Status int32 `gorm:"column:status;type:integer;not null;default:1;comment:产品状态:0-禁用,1-正常" json:"status"` // 产品状态:0-禁用,1-正常
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName Product's table name
|
||||
func (*Product) TableName() string {
|
||||
return TableNameProduct
|
||||
}
|
||||
23
web/models/product.go
Normal file
23
web/models/product.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/core"
|
||||
)
|
||||
|
||||
// Product 产品表
|
||||
type Product struct {
|
||||
core.Model
|
||||
Code string `json:"code" gorm:"column:code"` // 产品代码
|
||||
Name string `json:"name" gorm:"column:name"` // 产品名称
|
||||
Description *string `json:"description" gorm:"column:description"` // 产品描述
|
||||
Sort int32 `json:"sort" gorm:"column:sort"` // 排序
|
||||
Status ProductStatus `json:"status" gorm:"column:status"` // 产品状态:0-禁用,1-正常
|
||||
}
|
||||
|
||||
// ProductStatus 产品状态枚举
|
||||
type ProductStatus int
|
||||
|
||||
const (
|
||||
ProductStatusDisabled ProductStatus = 0 // 禁用
|
||||
ProductStatusEnabled ProductStatus = 1 // 正常
|
||||
)
|
||||
@@ -1,33 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameProxy = "proxy"
|
||||
|
||||
// Proxy mapped from table <proxy>
|
||||
type Proxy struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:代理服务ID" json:"id"` // 代理服务ID
|
||||
Version int32 `gorm:"column:version;type:integer;not null;comment:代理服务版本" json:"version"` // 代理服务版本
|
||||
Name string `gorm:"column:name;type:character varying(255);not null;comment:代理服务名称" json:"name"` // 代理服务名称
|
||||
Host string `gorm:"column:host;type:character varying(255);not null;comment:代理服务地址" json:"host"` // 代理服务地址
|
||||
Secret *string `gorm:"column:secret;type:character varying(255);comment:代理服务密钥" json:"secret"` // 代理服务密钥
|
||||
Type int32 `gorm:"column:type;type:integer;not null;comment:代理服务类型:1-三方,2-自有" json:"type"` // 代理服务类型:1-三方,2-自有
|
||||
Status int32 `gorm:"column:status;type:integer;not null;comment:代理服务状态:0-离线,1-在线" json:"status"` // 代理服务状态:0-离线,1-在线
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
Edges []Edge `gorm:"foreignKey:ProxyID;references:ID" json:"edges"`
|
||||
}
|
||||
|
||||
// TableName Proxy's table name
|
||||
func (*Proxy) TableName() string {
|
||||
return TableNameProxy
|
||||
}
|
||||
38
web/models/proxy.go
Normal file
38
web/models/proxy.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/core"
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
// Proxy 代理服务表
|
||||
type Proxy struct {
|
||||
core.Model
|
||||
Version int32 `json:"version" gorm:"column:version"` // 代理服务版本
|
||||
Mac string `json:"mac" gorm:"column:mac"` // 代理服务名称
|
||||
IP orm.Inet `json:"ip" gorm:"column:ip;not null"` // 代理服务地址
|
||||
Secret *string `json:"secret" gorm:"column:secret"` // 代理服务密钥
|
||||
Type ProxyType `json:"type" gorm:"column:type"` // 代理服务类型:1-自有,2-白银
|
||||
Status ProxyStatus `json:"status" gorm:"column:status"` // 代理服务状态:0-离线,1-在线
|
||||
Meta *datatypes.JSONType[any] `json:"meta" gorm:"column:meta"` // 代理服务元信息
|
||||
|
||||
Channels []Channel `json:"channels" gorm:"foreignkey:ProxyID"`
|
||||
}
|
||||
|
||||
// ProxyType 代理服务类型枚举
|
||||
type ProxyType int
|
||||
|
||||
const (
|
||||
ProxyTypeSelfHosted ProxyType = 1 // 自有
|
||||
ProxyTypeBaiYin ProxyType = 2 // 白银
|
||||
)
|
||||
|
||||
// ProxyStatus 代理服务状态枚举
|
||||
type ProxyStatus int
|
||||
|
||||
const (
|
||||
ProxyStatusOffline ProxyStatus = 0 // 离线
|
||||
ProxyStatusOnline ProxyStatus = 1 // 在线
|
||||
)
|
||||
@@ -1,32 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameRefund = "refund"
|
||||
|
||||
// Refund mapped from table <refund>
|
||||
type Refund struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:退款ID" json:"id"` // 退款ID
|
||||
TradeID int32 `gorm:"column:trade_id;type:integer;not null;comment:订单ID" json:"trade_id"` // 订单ID
|
||||
ProductID *int32 `gorm:"column:product_id;type:integer;comment:产品ID" json:"product_id"` // 产品ID
|
||||
Amount decimal.Decimal `gorm:"column:amount;type:numeric(12,2);not null;comment:退款金额" json:"amount"` // 退款金额
|
||||
Reason *string `gorm:"column:reason;type:character varying(255);comment:退款原因" json:"reason"` // 退款原因
|
||||
Status int32 `gorm:"column:status;type:integer;not null;comment:退款状态:0-待处理,1-已退款,2-已拒绝" json:"status"` // 退款状态:0-待处理,1-已退款,2-已拒绝
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName Refund's table name
|
||||
func (*Refund) TableName() string {
|
||||
return TableNameRefund
|
||||
}
|
||||
26
web/models/refund.go
Normal file
26
web/models/refund.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/core"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
// Refund 退款记录表
|
||||
type Refund struct {
|
||||
core.Model
|
||||
TradeID int32 `json:"trade_id" gorm:"column:trade_id"` // 订单ID
|
||||
ProductID *int32 `json:"product_id" gorm:"column:product_id"` // 产品ID
|
||||
Amount decimal.Decimal `json:"amount" gorm:"column:amount"` // 退款金额
|
||||
Reason *string `json:"reason" gorm:"column:reason"` // 退款原因
|
||||
Status RefundStatus `json:"status" gorm:"column:status"` // 退款状态:0-待处理,1-已退款,2-已拒绝
|
||||
}
|
||||
|
||||
// RefundStatus 退款状态枚举
|
||||
type RefundStatus int
|
||||
|
||||
const (
|
||||
RefundStatusPending RefundStatus = 0 // 待处理
|
||||
RefundStatusRefunded RefundStatus = 1 // 已退款
|
||||
RefundStatusRejected RefundStatus = 2 // 已拒绝
|
||||
)
|
||||
@@ -1,32 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameResource = "resource"
|
||||
|
||||
// Resource mapped from table <resource>
|
||||
type Resource struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:套餐ID" json:"id"` // 套餐ID
|
||||
UserID int32 `gorm:"column:user_id;type:integer;not null;comment:用户ID" json:"user_id"` // 用户ID
|
||||
ResourceNo *string `gorm:"column:resource_no;type:character varying(255);comment:套餐编号" json:"resource_no"` // 套餐编号
|
||||
Active bool `gorm:"column:active;type:boolean;not null;default:true;comment:套餐状态" json:"active"` // 套餐状态
|
||||
Type int32 `gorm:"column:type;type:integer;not null;comment:套餐类型:1-短效动态,2-长效动态" json:"type"` // 套餐类型:1-短效动态,2-长效动态
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
Short *ResourceShort `gorm:"foreignKey:ResourceID;references:ID" json:"short"`
|
||||
Long *ResourceLong `gorm:"foreignKey:ResourceID;references:ID" json:"long"`
|
||||
}
|
||||
|
||||
// TableName Resource's table name
|
||||
func (*Resource) TableName() string {
|
||||
return TableNameResource
|
||||
}
|
||||
34
web/models/resource.go
Normal file
34
web/models/resource.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/core"
|
||||
)
|
||||
|
||||
// Resource 套餐表
|
||||
type Resource struct {
|
||||
core.Model
|
||||
UserID int32 `json:"user_id" gorm:"column:user_id"` // 用户ID
|
||||
ResourceNo *string `json:"resource_no" gorm:"column:resource_no"` // 套餐编号
|
||||
Active bool `json:"active" gorm:"column:active"` // 套餐状态
|
||||
Type ResourceType `json:"type" gorm:"column:type"` // 套餐类型:1-短效动态,2-长效动态
|
||||
|
||||
User User `json:"user" gorm:"foreignKey:UserID"`
|
||||
Short *ResourceShort `json:"short" gorm:"foreignKey:ResourceID"`
|
||||
Long *ResourceLong `json:"long" gorm:"foreignKey:ResourceID"`
|
||||
}
|
||||
|
||||
// ResourceType 套餐类型枚举
|
||||
type ResourceType int
|
||||
|
||||
const (
|
||||
ResourceTypeShort ResourceType = 1 // 短效动态
|
||||
ResourceTypeLong ResourceType = 2 // 长效动态
|
||||
)
|
||||
|
||||
// ResourceLongType 套餐计费模式枚举
|
||||
type ResourceMode int
|
||||
|
||||
const (
|
||||
ResourceModeTime ResourceMode = 1 // 包时
|
||||
ResourceModeQuota ResourceMode = 2 // 包量
|
||||
)
|
||||
@@ -1,28 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import "platform/web/globals/orm"
|
||||
|
||||
const TableNameResourceLong = "resource_long"
|
||||
|
||||
// ResourceLong mapped from table <resource_long>
|
||||
type ResourceLong struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:ID" json:"id"` // ID
|
||||
ResourceID int32 `gorm:"column:resource_id;type:integer;not null;comment:套餐ID" json:"resource_id"` // 套餐ID
|
||||
Type int32 `gorm:"column:type;type:integer;not null;comment:套餐类型:1-包时,2-包量" json:"type"` // 套餐类型:1-包时,2-包量
|
||||
Live int32 `gorm:"column:live;type:integer;not null;comment:可用时长(天)" json:"live"` // 可用时长(天)
|
||||
Expire *orm.LocalDateTime `gorm:"column:expire;type:timestamp without time zone;comment:过期时间" json:"expire"` // 过期时间
|
||||
Quota *int32 `gorm:"column:quota;type:integer;comment:配额数量" json:"quota"` // 配额数量
|
||||
Used int32 `gorm:"column:used;type:integer;not null;comment:已用数量" json:"used"` // 已用数量
|
||||
DailyLimit int32 `gorm:"column:daily_limit;type:integer;not null;comment:每日限制" json:"daily_limit"` // 每日限制
|
||||
DailyUsed int32 `gorm:"column:daily_used;type:integer;not null;comment:今日已用数量" json:"daily_used"` // 今日已用数量
|
||||
DailyLast *orm.LocalDateTime `gorm:"column:daily_last;type:timestamp without time zone;comment:今日最后使用时间" json:"daily_last"` // 今日最后使用时间
|
||||
}
|
||||
|
||||
// TableName ResourceLong's table name
|
||||
func (*ResourceLong) TableName() string {
|
||||
return TableNameResourceLong
|
||||
}
|
||||
19
web/models/resource_long.go
Normal file
19
web/models/resource_long.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// ResourceLong 长效动态套餐表
|
||||
type ResourceLong struct {
|
||||
ID int32 `json:"id" gorm:"column:id"` // ID
|
||||
ResourceID int32 `json:"resource_id" gorm:"column:resource_id"` // 套餐ID
|
||||
Type ResourceMode `json:"type" gorm:"column:type"` // 套餐类型:1-包时,2-包量
|
||||
Live int32 `json:"live" gorm:"column:live"` // 可用时长(天)
|
||||
Expire *time.Time `json:"expire" gorm:"column:expire"` // 过期时间
|
||||
Quota *int32 `json:"quota" gorm:"column:quota"` // 配额数量
|
||||
Used int32 `json:"used" gorm:"column:used"` // 已用数量
|
||||
DailyLimit int32 `json:"daily_limit" gorm:"column:daily_limit"` // 每日限制
|
||||
DailyUsed int32 `json:"daily_used" gorm:"column:daily_used"` // 今日已用数量
|
||||
DailyLast *time.Time `json:"daily_last" gorm:"column:daily_last"` // 今日最后使用时间
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import "platform/web/globals/orm"
|
||||
|
||||
const TableNameResourceShort = "resource_short"
|
||||
|
||||
// ResourceShort mapped from table <resource_short>
|
||||
type ResourceShort struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:ID" json:"id"` // ID
|
||||
ResourceID int32 `gorm:"column:resource_id;type:integer;not null;comment:套餐ID" json:"resource_id"` // 套餐ID
|
||||
Type int32 `gorm:"column:type;type:integer;not null;comment:套餐类型:1-包时,2-包量" json:"type"` // 套餐类型:1-包时,2-包量
|
||||
Live int32 `gorm:"column:live;type:integer;not null;comment:可用时长(秒)" json:"live"` // 可用时长(秒)
|
||||
Expire *orm.LocalDateTime `gorm:"column:expire;type:timestamp without time zone;comment:过期时间" json:"expire"` // 过期时间
|
||||
Quota *int32 `gorm:"column:quota;type:integer;comment:配额数量" json:"quota"` // 配额数量
|
||||
Used int32 `gorm:"column:used;type:integer;not null;comment:已用数量" json:"used"` // 已用数量
|
||||
DailyLimit int32 `gorm:"column:daily_limit;type:integer;not null;comment:每日限制" json:"daily_limit"` // 每日限制
|
||||
DailyUsed int32 `gorm:"column:daily_used;type:integer;not null;comment:今日已用数量" json:"daily_used"` // 今日已用数量
|
||||
DailyLast *orm.LocalDateTime `gorm:"column:daily_last;type:timestamp without time zone;comment:今日最后使用时间" json:"daily_last"` // 今日最后使用时间
|
||||
}
|
||||
|
||||
// TableName ResourceShort's table name
|
||||
func (*ResourceShort) TableName() string {
|
||||
return TableNameResourceShort
|
||||
}
|
||||
19
web/models/resource_short.go
Normal file
19
web/models/resource_short.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// ResourceShort 短效动态套餐表
|
||||
type ResourceShort struct {
|
||||
ID int32 `json:"id" gorm:"column:id"` // ID
|
||||
ResourceID int32 `json:"resource_id" gorm:"column:resource_id"` // 套餐ID
|
||||
Type ResourceMode `json:"type" gorm:"column:type"` // 套餐类型:1-包时,2-包量
|
||||
Live int32 `json:"live" gorm:"column:live"` // 可用时长(秒)
|
||||
Expire *time.Time `json:"expire" gorm:"column:expire"` // 过期时间
|
||||
Quota *int32 `json:"quota" gorm:"column:quota"` // 配额数量
|
||||
Used int32 `json:"used" gorm:"column:used"` // 已用数量
|
||||
DailyLimit int32 `json:"daily_limit" gorm:"column:daily_limit"` // 每日限制
|
||||
DailyUsed int32 `json:"daily_used" gorm:"column:daily_used"` // 今日已用数量
|
||||
DailyLast *time.Time `json:"daily_last" gorm:"column:daily_last"` // 今日最后使用时间
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameSession = "session"
|
||||
|
||||
// Session mapped from table <session>
|
||||
type Session struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:会话ID" json:"id"` // 会话ID
|
||||
UserID *int32 `gorm:"column:user_id;type:integer;comment:用户ID" json:"user_id"` // 用户ID
|
||||
AdminID *int32 `gorm:"column:admin_id;type:integer;comment:管理员ID" json:"admin_id"` // 管理员ID
|
||||
ClientID *int32 `gorm:"column:client_id;type:integer;comment:客户端ID" json:"client_id"` // 客户端ID
|
||||
IP *string `gorm:"column:ip;type:character varying(45);comment:IP地址" json:"ip"` // IP地址
|
||||
UA *string `gorm:"column:ua;type:character varying(255);comment:用户代理" json:"ua"` // 用户代理
|
||||
AccessToken string `gorm:"column:access_token;type:character varying(255);not null;comment:访问令牌" json:"access_token"` // 访问令牌
|
||||
AccessTokenExpires orm.LocalDateTime `gorm:"column:access_token_expires;type:timestamp without time zone;not null;comment:访问令牌过期时间" json:"access_token_expires"` // 访问令牌过期时间
|
||||
RefreshToken *string `gorm:"column:refresh_token;type:character varying(255);comment:刷新令牌" json:"refresh_token"` // 刷新令牌
|
||||
RefreshTokenExpires *orm.LocalDateTime `gorm:"column:refresh_token_expires;type:timestamp without time zone;comment:刷新令牌过期时间" json:"refresh_token_expires"` // 刷新令牌过期时间
|
||||
Scopes_ *string `gorm:"column:scopes;type:character varying(255);comment:权限范围" json:"scopes"` // 权限范围
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
User *User `gorm:"foreignKey:UserID" json:"user"`
|
||||
Admin *Admin `gorm:"foreignKey:UserID" json:"admin"`
|
||||
Client *Client `gorm:"belongsTo:ID;foreignKey:ClientID" json:"client"`
|
||||
}
|
||||
|
||||
// TableName Session's table name
|
||||
func (*Session) TableName() string {
|
||||
return TableNameSession
|
||||
}
|
||||
26
web/models/session.go
Normal file
26
web/models/session.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/core"
|
||||
"platform/web/globals/orm"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Session 会话表
|
||||
type Session struct {
|
||||
core.Model
|
||||
UserID *int32 `json:"user_id" gorm:"column:user_id"` // 用户ID
|
||||
AdminID *int32 `json:"admin_id" gorm:"column:admin_id"` // 管理员ID
|
||||
ClientID *int32 `json:"client_id" gorm:"column:client_id"` // 客户端ID
|
||||
IP *orm.Inet `json:"ip" gorm:"column:ip"` // IP地址
|
||||
UA *string `json:"ua" gorm:"column:ua"` // 用户代理
|
||||
AccessToken string `json:"access_token" gorm:"column:access_token"` // 访问令牌
|
||||
AccessTokenExpires time.Time `json:"access_token_expires" gorm:"column:access_token_expires"` // 访问令牌过期时间
|
||||
RefreshToken *string `json:"refresh_token" gorm:"column:refresh_token"` // 刷新令牌
|
||||
RefreshTokenExpires *time.Time `json:"refresh_token_expires" gorm:"column:refresh_token_expires"` // 刷新令牌过期时间
|
||||
Scopes *string `json:"scopes" gorm:"column:scopes"` // 权限范围
|
||||
|
||||
User *User `json:"user" gorm:"foreignKey:UserID"`
|
||||
Admin *Admin `json:"admin" gorm:"foreignKey:AdminID"`
|
||||
Client *Client `json:"client" gorm:"foreignKey:ClientID;belongsTo:ID"`
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameTrade = "trade"
|
||||
|
||||
// Trade mapped from table <trade>
|
||||
type Trade struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:订单ID" json:"id"` // 订单ID
|
||||
UserID int32 `gorm:"column:user_id;type:integer;not null;comment:用户ID" json:"user_id"` // 用户ID
|
||||
InnerNo string `gorm:"column:inner_no;type:character varying(255);not null;comment:内部订单号" json:"inner_no"` // 内部订单号
|
||||
OuterNo *string `gorm:"column:outer_no;type:character varying(255);comment:外部订单号" json:"outer_no"` // 外部订单号
|
||||
Type int32 `gorm:"column:type;type:integer;not null;comment:订单类型:1-购买产品,2-充值余额" json:"type"` // 订单类型:1-购买产品,2-充值余额
|
||||
Subject string `gorm:"column:subject;type:character varying(255);not null;comment:订单主题" json:"subject"` // 订单主题
|
||||
Remark *string `gorm:"column:remark;type:character varying(255);comment:订单备注" json:"remark"` // 订单备注
|
||||
Amount decimal.Decimal `gorm:"column:amount;type:numeric(12,2);not null;comment:订单总金额" json:"amount"` // 订单总金额
|
||||
Payment decimal.Decimal `gorm:"column:payment;type:numeric(12,2);not null;comment:实际支付金额" json:"payment"` // 实际支付金额
|
||||
Method int32 `gorm:"column:method;type:integer;not null;comment:支付方式:1-支付宝,2-微信,3-商福通,4-商福通渠道支付宝,5-商福通渠道微信" json:"method"` // 支付方式:1-支付宝,2-微信,3-商福通,4-商福通渠道支付宝,5-商福通渠道微信
|
||||
Platform int32 `gorm:"column:platform;type:integer;not null;comment:支付平台:1-电脑网站,2-手机网站" json:"platform"` // 支付平台:1-电脑网站,2-手机网站
|
||||
Acquirer *int32 `gorm:"column:acquirer;type:integer;comment:收单机构:1-支付宝,2-微信,3-银联" json:"acquirer"` // 收单机构:1-支付宝,2-微信,3-银联
|
||||
Status int32 `gorm:"column:status;type:integer;not null;comment:订单状态:0-待支付,1-已支付,2-已取消" json:"status"` // 订单状态:0-待支付,1-已支付,2-已取消
|
||||
Refunded bool `gorm:"column:refunded;type:boolean;not null" json:"refunded"`
|
||||
PaymentURL *string `gorm:"column:payment_url;type:text;comment:支付链接" json:"payment_url"` // 支付链接
|
||||
CompletedAt *orm.LocalDateTime `gorm:"column:completed_at;type:timestamp without time zone;comment:支付时间" json:"completed_at"` // 支付时间
|
||||
CanceledAt *orm.LocalDateTime `gorm:"column:canceled_at;type:timestamp without time zone;comment:取消时间" json:"canceled_at"` // 取消时间
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName Trade's table name
|
||||
func (*Trade) TableName() string {
|
||||
return TableNameTrade
|
||||
}
|
||||
74
web/models/trade.go
Normal file
74
web/models/trade.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/core"
|
||||
"time"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
// Trade 订单表
|
||||
type Trade struct {
|
||||
core.Model
|
||||
UserID int32 `json:"user_id" gorm:"column:user_id"` // 用户ID
|
||||
InnerNo string `json:"inner_no" gorm:"column:inner_no"` // 内部订单号
|
||||
OuterNo *string `json:"outer_no" gorm:"column:outer_no"` // 外部订单号
|
||||
Type TradeType `json:"type" gorm:"column:type"` // 订单类型:1-购买产品,2-充值余额
|
||||
Subject string `json:"subject" gorm:"column:subject"` // 订单主题
|
||||
Remark *string `json:"remark" gorm:"column:remark"` // 订单备注
|
||||
Amount decimal.Decimal `json:"amount" gorm:"column:amount"` // 订单总金额
|
||||
Payment decimal.Decimal `json:"payment" gorm:"column:payment"` // 实际支付金额
|
||||
Method TradeMethod `json:"method" gorm:"column:method"` // 支付方式:1-支付宝,2-微信,3-商福通,4-商福通渠道支付宝,5-商福通渠道微信
|
||||
Platform TradePlatform `json:"platform" gorm:"column:platform"` // 支付平台:1-电脑网站,2-手机网站
|
||||
Acquirer *TradeAcquirer `json:"acquirer" gorm:"column:acquirer"` // 收单机构:1-支付宝,2-微信,3-银联
|
||||
Status TradeStatus `json:"status" gorm:"column:status"` // 订单状态:0-待支付,1-已支付,2-已取消
|
||||
Refunded bool `json:"refunded" gorm:"column:refunded"` // 是否已退款
|
||||
PaymentURL *string `json:"payment_url" gorm:"column:payment_url"` // 支付链接
|
||||
CompletedAt *time.Time `json:"completed_at" gorm:"column:completed_at"` // 支付时间
|
||||
CanceledAt *time.Time `json:"canceled_at" gorm:"column:canceled_at"` // 取消时间
|
||||
}
|
||||
|
||||
// TradeType 订单类型枚举
|
||||
type TradeType int
|
||||
|
||||
const (
|
||||
TradeTypePurchase TradeType = 1 // 购买产品
|
||||
TradeTypeRecharge TradeType = 2 // 充值余额
|
||||
)
|
||||
|
||||
// TradeMethod 支付方式枚举
|
||||
type TradeMethod int
|
||||
|
||||
const (
|
||||
TradeMethodAlipay TradeMethod = 1 // 支付宝
|
||||
TradeMethodWechat TradeMethod = 2 // 微信
|
||||
TradeMethodSft TradeMethod = 3 // 商福通
|
||||
TradeMethodSftAlipay TradeMethod = 4 // 商福通渠道支付宝
|
||||
TradeMethodSftWechat TradeMethod = 5 // 商福通渠道微信
|
||||
)
|
||||
|
||||
// TradePlatform 支付平台枚举
|
||||
type TradePlatform int
|
||||
|
||||
const (
|
||||
TradePlatformPC TradePlatform = 1 // 电脑网站
|
||||
TradePlatformMobile TradePlatform = 2 // 手机网站
|
||||
)
|
||||
|
||||
// TradeAcquirer 收单机构枚举
|
||||
type TradeAcquirer int
|
||||
|
||||
const (
|
||||
TradeAcquirerAlipay TradeAcquirer = 1 // 支付宝
|
||||
TradeAcquirerWechat TradeAcquirer = 2 // 微信
|
||||
TradeAcquirerUnionPay TradeAcquirer = 3 // 银联
|
||||
)
|
||||
|
||||
// TradeStatus 订单状态枚举
|
||||
type TradeStatus int
|
||||
|
||||
const (
|
||||
TradeStatusPending TradeStatus = 0 // 待支付
|
||||
TradeStatusSuccess TradeStatus = 1 // 已支付
|
||||
TradeStatusCanceled TradeStatus = 2 // 已取消
|
||||
)
|
||||
@@ -1,44 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameUser = "user"
|
||||
|
||||
// User mapped from table <user>
|
||||
type User struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:用户ID" json:"id"` // 用户ID
|
||||
AdminID *int32 `gorm:"column:admin_id;type:integer;comment:管理员ID" json:"admin_id"` // 管理员ID
|
||||
Phone string `gorm:"column:phone;type:character varying(255);not null;comment:手机号码" json:"phone"` // 手机号码
|
||||
Username *string `gorm:"column:username;type:character varying(255);comment:用户名" json:"username"` // 用户名
|
||||
Email *string `gorm:"column:email;type:character varying(255)" json:"email"`
|
||||
Password *string `gorm:"column:password;type:character varying(255);comment:用户密码" json:"password"` // 用户密码
|
||||
Name *string `gorm:"column:name;type:character varying(255);comment:真实姓名" json:"name"` // 真实姓名
|
||||
Avatar *string `gorm:"column:avatar;type:character varying(255);comment:头像URL" json:"avatar"` // 头像URL
|
||||
Status int32 `gorm:"column:status;type:integer;not null;default:1;comment:用户状态:0-禁用,1-正常" json:"status"` // 用户状态:0-禁用,1-正常
|
||||
Balance decimal.Decimal `gorm:"column:balance;type:numeric(12,2);not null;comment:账户余额" json:"balance"` // 账户余额
|
||||
IDType int32 `gorm:"column:id_type;type:integer;not null;comment:认证类型:0-未认证,1-个人认证,2-企业认证" json:"id_type"` // 认证类型:0-未认证,1-个人认证,2-企业认证
|
||||
IDNo *string `gorm:"column:id_no;type:character varying(255);comment:身份证号或营业执照号" json:"id_no"` // 身份证号或营业执照号
|
||||
IDToken *string `gorm:"column:id_token;type:character varying(255);comment:身份验证标识" json:"id_token"` // 身份验证标识
|
||||
ContactQQ *string `gorm:"column:contact_qq;type:character varying(255);comment:QQ联系方式" json:"contact_qq"` // QQ联系方式
|
||||
ContactWechat *string `gorm:"column:contact_wechat;type:character varying(255);comment:微信联系方式" json:"contact_wechat"` // 微信联系方式
|
||||
LastLogin *orm.LocalDateTime `gorm:"column:last_login;type:timestamp without time zone;comment:最后登录时间" json:"last_login"` // 最后登录时间
|
||||
LastLoginHost *string `gorm:"column:last_login_host;type:character varying(45);comment:最后登录地址" json:"last_login_host"` // 最后登录地址
|
||||
LastLoginAgent *string `gorm:"column:last_login_agent;type:character varying(255);comment:最后登录代理" json:"last_login_agent"` // 最后登录代理
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName User's table name
|
||||
func (*User) TableName() string {
|
||||
return TableNameUser
|
||||
}
|
||||
50
web/models/user.go
Normal file
50
web/models/user.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/core"
|
||||
"platform/web/globals/orm"
|
||||
"time"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
// User 用户表
|
||||
type User struct {
|
||||
core.Model
|
||||
AdminID *int32 `json:"admin_id" gorm:"column:admin_id"` // 管理员ID
|
||||
Phone string `json:"phone" gorm:"column:phone"` // 手机号码
|
||||
Username *string `json:"username" gorm:"column:username"` // 用户名
|
||||
Email *string `json:"email" gorm:"column:email"` // 邮箱
|
||||
Password *string `json:"password" gorm:"column:password"` // 用户密码
|
||||
Name *string `json:"name" gorm:"column:name"` // 真实姓名
|
||||
Avatar *string `json:"avatar" gorm:"column:avatar"` // 头像URL
|
||||
Status UserStatus `json:"status" gorm:"column:status"` // 用户状态:0-禁用,1-正常
|
||||
Balance decimal.Decimal `json:"balance" gorm:"column:balance"` // 账户余额
|
||||
IDType UserIDType `json:"id_type" gorm:"column:id_type"` // 认证类型:0-未认证,1-个人认证,2-企业认证
|
||||
IDNo *string `json:"id_no" gorm:"column:id_no"` // 身份证号或营业执照号
|
||||
IDToken *string `json:"id_token" gorm:"column:id_token"` // 身份验证标识
|
||||
ContactQQ *string `json:"contact_qq" gorm:"column:contact_qq"` // QQ联系方式
|
||||
ContactWechat *string `json:"contact_wechat" gorm:"column:contact_wechat"` // 微信联系方式
|
||||
LastLogin *time.Time `json:"last_login" gorm:"column:last_login"` // 最后登录时间
|
||||
LastLoginIP *orm.Inet `json:"last_login_ip" gorm:"column:last_login_ip"` // 最后登录地址
|
||||
LastLoginUA *string `json:"last_login_ua" gorm:"column:last_login_ua"` // 最后登录代理
|
||||
|
||||
Admin Admin `json:"admin" gorm:"foreignKey:AdminID"`
|
||||
}
|
||||
|
||||
// UserStatus 用户状态枚举
|
||||
type UserStatus int
|
||||
|
||||
const (
|
||||
UserStatusDisabled UserStatus = 0 // 禁用
|
||||
UserStatusEnabled UserStatus = 1 // 正常
|
||||
)
|
||||
|
||||
// UserIDType 用户认证类型枚举
|
||||
type UserIDType int
|
||||
|
||||
const (
|
||||
UserIDTypeUnverified UserIDType = 0 // 未认证
|
||||
UserIDTypePersonal UserIDType = 1 // 个人认证
|
||||
UserIDTypeEnterprise UserIDType = 2 // 企业认证
|
||||
)
|
||||
@@ -1,30 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameUserRole = "user_role"
|
||||
|
||||
// UserRole mapped from table <user_role>
|
||||
type UserRole struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:角色ID" json:"id"` // 角色ID
|
||||
Name string `gorm:"column:name;type:character varying(255);not null;comment:角色名称" json:"name"` // 角色名称
|
||||
Description *string `gorm:"column:description;type:character varying(255);comment:角色描述" json:"description"` // 角色描述
|
||||
Active *bool `gorm:"column:active;type:boolean;default:true;comment:是否激活" json:"active"` // 是否激活
|
||||
Sort *int32 `gorm:"column:sort;type:integer;comment:排序" json:"sort"` // 排序
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName UserRole's table name
|
||||
func (*UserRole) TableName() string {
|
||||
return TableNameUserRole
|
||||
}
|
||||
14
web/models/user_role.go
Normal file
14
web/models/user_role.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/core"
|
||||
)
|
||||
|
||||
// UserRole 用户角色表
|
||||
type UserRole struct {
|
||||
core.Model
|
||||
Name string `json:"name" gorm:"column:name"` // 角色名称
|
||||
Description *string `json:"description" gorm:"column:description"` // 角色描述
|
||||
Active bool `json:"active" gorm:"column:active"` // 是否激活
|
||||
Sort int32 `json:"sort" gorm:"column:sort"` // 排序
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameUserRoleLink = "user_role_link"
|
||||
|
||||
// UserRoleLink mapped from table <user_role_link>
|
||||
type UserRoleLink struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID
|
||||
UserID int32 `gorm:"column:user_id;type:integer;not null;comment:用户ID" json:"user_id"` // 用户ID
|
||||
RoleID int32 `gorm:"column:role_id;type:integer;not null;comment:角色ID" json:"role_id"` // 角色ID
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName UserRoleLink's table name
|
||||
func (*UserRoleLink) TableName() string {
|
||||
return TableNameUserRoleLink
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameUserRolePermissionLink = "user_role_permission_link"
|
||||
|
||||
// UserRolePermissionLink mapped from table <user_role_permission_link>
|
||||
type UserRolePermissionLink struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:关联ID" json:"id"` // 关联ID
|
||||
RoleID int32 `gorm:"column:role_id;type:integer;not null;comment:角色ID" json:"role_id"` // 角色ID
|
||||
PermissionID int32 `gorm:"column:permission_id;type:integer;not null;comment:权限ID" json:"permission_id"` // 权限ID
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName UserRolePermissionLink's table name
|
||||
func (*UserRolePermissionLink) TableName() string {
|
||||
return TableNameUserRolePermissionLink
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/globals/orm"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const TableNameWhitelist = "whitelist"
|
||||
|
||||
// Whitelist mapped from table <whitelist>
|
||||
type Whitelist struct {
|
||||
ID int32 `gorm:"column:id;type:integer;primaryKey;autoIncrement:true;comment:白名单ID" json:"id"` // 白名单ID
|
||||
UserID int32 `gorm:"column:user_id;type:integer;not null;comment:用户ID" json:"user_id"` // 用户ID
|
||||
Host string `gorm:"column:host;type:character varying(45);not null;comment:IP地址" json:"host"` // IP地址
|
||||
Remark *string `gorm:"column:remark;type:character varying(255);comment:备注" json:"remark"` // 备注
|
||||
CreatedAt *orm.LocalDateTime `gorm:"column:created_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间
|
||||
UpdatedAt *orm.LocalDateTime `gorm:"column:updated_at;type:timestamp without time zone;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp without time zone;comment:删除时间" json:"deleted_at"` // 删除时间
|
||||
}
|
||||
|
||||
// TableName Whitelist's table name
|
||||
func (*Whitelist) TableName() string {
|
||||
return TableNameWhitelist
|
||||
}
|
||||
14
web/models/whitelist.go
Normal file
14
web/models/whitelist.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"platform/web/core"
|
||||
"platform/web/globals/orm"
|
||||
)
|
||||
|
||||
// Whitelist 白名单表
|
||||
type Whitelist struct {
|
||||
core.Model
|
||||
UserID int32 `json:"user_id" gorm:"column:user_id"` // 用户ID
|
||||
IP orm.Inet `json:"ip" gorm:"column:ip;not null"` // IP地址
|
||||
Remark *string `json:"remark" gorm:"column:remark"` // 备注
|
||||
}
|
||||
@@ -28,19 +28,19 @@ func newAdmin(db *gorm.DB, opts ...gen.DOOption) admin {
|
||||
tableName := _admin.adminDo.TableName()
|
||||
_admin.ALL = field.NewAsterisk(tableName)
|
||||
_admin.ID = field.NewInt32(tableName, "id")
|
||||
_admin.CreatedAt = field.NewTime(tableName, "created_at")
|
||||
_admin.UpdatedAt = field.NewTime(tableName, "updated_at")
|
||||
_admin.DeletedAt = field.NewField(tableName, "deleted_at")
|
||||
_admin.Username = field.NewString(tableName, "username")
|
||||
_admin.Password = field.NewString(tableName, "password")
|
||||
_admin.Name = field.NewString(tableName, "name")
|
||||
_admin.Avatar = field.NewString(tableName, "avatar")
|
||||
_admin.Phone = field.NewString(tableName, "phone")
|
||||
_admin.Email = field.NewString(tableName, "email")
|
||||
_admin.Status = field.NewInt32(tableName, "status")
|
||||
_admin.LastLogin = field.NewField(tableName, "last_login")
|
||||
_admin.LastLoginHost = field.NewString(tableName, "last_login_host")
|
||||
_admin.LastLoginAgent = field.NewString(tableName, "last_login_agent")
|
||||
_admin.CreatedAt = field.NewField(tableName, "created_at")
|
||||
_admin.UpdatedAt = field.NewField(tableName, "updated_at")
|
||||
_admin.DeletedAt = field.NewField(tableName, "deleted_at")
|
||||
_admin.Status = field.NewInt(tableName, "status")
|
||||
_admin.LastLogin = field.NewTime(tableName, "last_login")
|
||||
_admin.LastLoginIP = field.NewField(tableName, "last_login_ip")
|
||||
_admin.LastLoginUA = field.NewString(tableName, "last_login_ua")
|
||||
|
||||
_admin.fillFieldMap()
|
||||
|
||||
@@ -50,21 +50,21 @@ func newAdmin(db *gorm.DB, opts ...gen.DOOption) admin {
|
||||
type admin struct {
|
||||
adminDo
|
||||
|
||||
ALL field.Asterisk
|
||||
ID field.Int32 // 管理员ID
|
||||
Username field.String // 用户名
|
||||
Password field.String // 密码
|
||||
Name field.String // 真实姓名
|
||||
Avatar field.String // 头像URL
|
||||
Phone field.String // 手机号码
|
||||
Email field.String // 邮箱
|
||||
Status field.Int32 // 状态:0-禁用,1-正常
|
||||
LastLogin field.Field // 最后登录时间
|
||||
LastLoginHost field.String // 最后登录地址
|
||||
LastLoginAgent field.String // 最后登录代理
|
||||
CreatedAt field.Field // 创建时间
|
||||
UpdatedAt field.Field // 更新时间
|
||||
DeletedAt field.Field // 删除时间
|
||||
ALL field.Asterisk
|
||||
ID field.Int32
|
||||
CreatedAt field.Time
|
||||
UpdatedAt field.Time
|
||||
DeletedAt field.Field
|
||||
Username field.String
|
||||
Password field.String
|
||||
Name field.String
|
||||
Avatar field.String
|
||||
Phone field.String
|
||||
Email field.String
|
||||
Status field.Int
|
||||
LastLogin field.Time
|
||||
LastLoginIP field.Field
|
||||
LastLoginUA field.String
|
||||
|
||||
fieldMap map[string]field.Expr
|
||||
}
|
||||
@@ -82,19 +82,19 @@ func (a admin) As(alias string) *admin {
|
||||
func (a *admin) updateTableName(table string) *admin {
|
||||
a.ALL = field.NewAsterisk(table)
|
||||
a.ID = field.NewInt32(table, "id")
|
||||
a.CreatedAt = field.NewTime(table, "created_at")
|
||||
a.UpdatedAt = field.NewTime(table, "updated_at")
|
||||
a.DeletedAt = field.NewField(table, "deleted_at")
|
||||
a.Username = field.NewString(table, "username")
|
||||
a.Password = field.NewString(table, "password")
|
||||
a.Name = field.NewString(table, "name")
|
||||
a.Avatar = field.NewString(table, "avatar")
|
||||
a.Phone = field.NewString(table, "phone")
|
||||
a.Email = field.NewString(table, "email")
|
||||
a.Status = field.NewInt32(table, "status")
|
||||
a.LastLogin = field.NewField(table, "last_login")
|
||||
a.LastLoginHost = field.NewString(table, "last_login_host")
|
||||
a.LastLoginAgent = field.NewString(table, "last_login_agent")
|
||||
a.CreatedAt = field.NewField(table, "created_at")
|
||||
a.UpdatedAt = field.NewField(table, "updated_at")
|
||||
a.DeletedAt = field.NewField(table, "deleted_at")
|
||||
a.Status = field.NewInt(table, "status")
|
||||
a.LastLogin = field.NewTime(table, "last_login")
|
||||
a.LastLoginIP = field.NewField(table, "last_login_ip")
|
||||
a.LastLoginUA = field.NewString(table, "last_login_ua")
|
||||
|
||||
a.fillFieldMap()
|
||||
|
||||
@@ -113,6 +113,9 @@ func (a *admin) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||
func (a *admin) fillFieldMap() {
|
||||
a.fieldMap = make(map[string]field.Expr, 14)
|
||||
a.fieldMap["id"] = a.ID
|
||||
a.fieldMap["created_at"] = a.CreatedAt
|
||||
a.fieldMap["updated_at"] = a.UpdatedAt
|
||||
a.fieldMap["deleted_at"] = a.DeletedAt
|
||||
a.fieldMap["username"] = a.Username
|
||||
a.fieldMap["password"] = a.Password
|
||||
a.fieldMap["name"] = a.Name
|
||||
@@ -121,11 +124,8 @@ func (a *admin) fillFieldMap() {
|
||||
a.fieldMap["email"] = a.Email
|
||||
a.fieldMap["status"] = a.Status
|
||||
a.fieldMap["last_login"] = a.LastLogin
|
||||
a.fieldMap["last_login_host"] = a.LastLoginHost
|
||||
a.fieldMap["last_login_agent"] = a.LastLoginAgent
|
||||
a.fieldMap["created_at"] = a.CreatedAt
|
||||
a.fieldMap["updated_at"] = a.UpdatedAt
|
||||
a.fieldMap["deleted_at"] = a.DeletedAt
|
||||
a.fieldMap["last_login_ip"] = a.LastLoginIP
|
||||
a.fieldMap["last_login_ua"] = a.LastLoginUA
|
||||
}
|
||||
|
||||
func (a admin) clone(db *gorm.DB) admin {
|
||||
|
||||
@@ -28,13 +28,13 @@ func newAdminRole(db *gorm.DB, opts ...gen.DOOption) adminRole {
|
||||
tableName := _adminRole.adminRoleDo.TableName()
|
||||
_adminRole.ALL = field.NewAsterisk(tableName)
|
||||
_adminRole.ID = field.NewInt32(tableName, "id")
|
||||
_adminRole.CreatedAt = field.NewTime(tableName, "created_at")
|
||||
_adminRole.UpdatedAt = field.NewTime(tableName, "updated_at")
|
||||
_adminRole.DeletedAt = field.NewField(tableName, "deleted_at")
|
||||
_adminRole.Name = field.NewString(tableName, "name")
|
||||
_adminRole.Description = field.NewString(tableName, "description")
|
||||
_adminRole.Active = field.NewBool(tableName, "active")
|
||||
_adminRole.Sort = field.NewInt32(tableName, "sort")
|
||||
_adminRole.CreatedAt = field.NewField(tableName, "created_at")
|
||||
_adminRole.UpdatedAt = field.NewField(tableName, "updated_at")
|
||||
_adminRole.DeletedAt = field.NewField(tableName, "deleted_at")
|
||||
|
||||
_adminRole.fillFieldMap()
|
||||
|
||||
@@ -45,14 +45,14 @@ type adminRole struct {
|
||||
adminRoleDo
|
||||
|
||||
ALL field.Asterisk
|
||||
ID field.Int32 // 管理员角色ID
|
||||
Name field.String // 角色名称
|
||||
Description field.String // 角色描述
|
||||
Active field.Bool // 是否激活
|
||||
Sort field.Int32 // 排序
|
||||
CreatedAt field.Field // 创建时间
|
||||
UpdatedAt field.Field // 更新时间
|
||||
DeletedAt field.Field // 删除时间
|
||||
ID field.Int32
|
||||
CreatedAt field.Time
|
||||
UpdatedAt field.Time
|
||||
DeletedAt field.Field
|
||||
Name field.String
|
||||
Description field.String
|
||||
Active field.Bool
|
||||
Sort field.Int32
|
||||
|
||||
fieldMap map[string]field.Expr
|
||||
}
|
||||
@@ -70,13 +70,13 @@ func (a adminRole) As(alias string) *adminRole {
|
||||
func (a *adminRole) updateTableName(table string) *adminRole {
|
||||
a.ALL = field.NewAsterisk(table)
|
||||
a.ID = field.NewInt32(table, "id")
|
||||
a.CreatedAt = field.NewTime(table, "created_at")
|
||||
a.UpdatedAt = field.NewTime(table, "updated_at")
|
||||
a.DeletedAt = field.NewField(table, "deleted_at")
|
||||
a.Name = field.NewString(table, "name")
|
||||
a.Description = field.NewString(table, "description")
|
||||
a.Active = field.NewBool(table, "active")
|
||||
a.Sort = field.NewInt32(table, "sort")
|
||||
a.CreatedAt = field.NewField(table, "created_at")
|
||||
a.UpdatedAt = field.NewField(table, "updated_at")
|
||||
a.DeletedAt = field.NewField(table, "deleted_at")
|
||||
|
||||
a.fillFieldMap()
|
||||
|
||||
@@ -95,13 +95,13 @@ func (a *adminRole) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||
func (a *adminRole) fillFieldMap() {
|
||||
a.fieldMap = make(map[string]field.Expr, 8)
|
||||
a.fieldMap["id"] = a.ID
|
||||
a.fieldMap["created_at"] = a.CreatedAt
|
||||
a.fieldMap["updated_at"] = a.UpdatedAt
|
||||
a.fieldMap["deleted_at"] = a.DeletedAt
|
||||
a.fieldMap["name"] = a.Name
|
||||
a.fieldMap["description"] = a.Description
|
||||
a.fieldMap["active"] = a.Active
|
||||
a.fieldMap["sort"] = a.Sort
|
||||
a.fieldMap["created_at"] = a.CreatedAt
|
||||
a.fieldMap["updated_at"] = a.UpdatedAt
|
||||
a.fieldMap["deleted_at"] = a.DeletedAt
|
||||
}
|
||||
|
||||
func (a adminRole) clone(db *gorm.DB) adminRole {
|
||||
|
||||
@@ -1,339 +0,0 @@
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
// Code generated by gorm.io/gen. DO NOT EDIT.
|
||||
|
||||
package queries
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
"gorm.io/gorm/schema"
|
||||
|
||||
"gorm.io/gen"
|
||||
"gorm.io/gen/field"
|
||||
|
||||
"gorm.io/plugin/dbresolver"
|
||||
|
||||
"platform/web/models"
|
||||
)
|
||||
|
||||
func newAdminRoleLink(db *gorm.DB, opts ...gen.DOOption) adminRoleLink {
|
||||
_adminRoleLink := adminRoleLink{}
|
||||
|
||||
_adminRoleLink.adminRoleLinkDo.UseDB(db, opts...)
|
||||
_adminRoleLink.adminRoleLinkDo.UseModel(&models.AdminRoleLink{})
|
||||
|
||||
tableName := _adminRoleLink.adminRoleLinkDo.TableName()
|
||||
_adminRoleLink.ALL = field.NewAsterisk(tableName)
|
||||
_adminRoleLink.ID = field.NewInt32(tableName, "id")
|
||||
_adminRoleLink.AdminID = field.NewInt32(tableName, "admin_id")
|
||||
_adminRoleLink.RoleID = field.NewInt32(tableName, "role_id")
|
||||
_adminRoleLink.CreatedAt = field.NewField(tableName, "created_at")
|
||||
_adminRoleLink.UpdatedAt = field.NewField(tableName, "updated_at")
|
||||
_adminRoleLink.DeletedAt = field.NewField(tableName, "deleted_at")
|
||||
|
||||
_adminRoleLink.fillFieldMap()
|
||||
|
||||
return _adminRoleLink
|
||||
}
|
||||
|
||||
type adminRoleLink struct {
|
||||
adminRoleLinkDo
|
||||
|
||||
ALL field.Asterisk
|
||||
ID field.Int32 // 关联ID
|
||||
AdminID field.Int32 // 管理员ID
|
||||
RoleID field.Int32 // 角色ID
|
||||
CreatedAt field.Field // 创建时间
|
||||
UpdatedAt field.Field // 更新时间
|
||||
DeletedAt field.Field // 删除时间
|
||||
|
||||
fieldMap map[string]field.Expr
|
||||
}
|
||||
|
||||
func (a adminRoleLink) Table(newTableName string) *adminRoleLink {
|
||||
a.adminRoleLinkDo.UseTable(newTableName)
|
||||
return a.updateTableName(newTableName)
|
||||
}
|
||||
|
||||
func (a adminRoleLink) As(alias string) *adminRoleLink {
|
||||
a.adminRoleLinkDo.DO = *(a.adminRoleLinkDo.As(alias).(*gen.DO))
|
||||
return a.updateTableName(alias)
|
||||
}
|
||||
|
||||
func (a *adminRoleLink) updateTableName(table string) *adminRoleLink {
|
||||
a.ALL = field.NewAsterisk(table)
|
||||
a.ID = field.NewInt32(table, "id")
|
||||
a.AdminID = field.NewInt32(table, "admin_id")
|
||||
a.RoleID = field.NewInt32(table, "role_id")
|
||||
a.CreatedAt = field.NewField(table, "created_at")
|
||||
a.UpdatedAt = field.NewField(table, "updated_at")
|
||||
a.DeletedAt = field.NewField(table, "deleted_at")
|
||||
|
||||
a.fillFieldMap()
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *adminRoleLink) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||
_f, ok := a.fieldMap[fieldName]
|
||||
if !ok || _f == nil {
|
||||
return nil, false
|
||||
}
|
||||
_oe, ok := _f.(field.OrderExpr)
|
||||
return _oe, ok
|
||||
}
|
||||
|
||||
func (a *adminRoleLink) fillFieldMap() {
|
||||
a.fieldMap = make(map[string]field.Expr, 6)
|
||||
a.fieldMap["id"] = a.ID
|
||||
a.fieldMap["admin_id"] = a.AdminID
|
||||
a.fieldMap["role_id"] = a.RoleID
|
||||
a.fieldMap["created_at"] = a.CreatedAt
|
||||
a.fieldMap["updated_at"] = a.UpdatedAt
|
||||
a.fieldMap["deleted_at"] = a.DeletedAt
|
||||
}
|
||||
|
||||
func (a adminRoleLink) clone(db *gorm.DB) adminRoleLink {
|
||||
a.adminRoleLinkDo.ReplaceConnPool(db.Statement.ConnPool)
|
||||
return a
|
||||
}
|
||||
|
||||
func (a adminRoleLink) replaceDB(db *gorm.DB) adminRoleLink {
|
||||
a.adminRoleLinkDo.ReplaceDB(db)
|
||||
return a
|
||||
}
|
||||
|
||||
type adminRoleLinkDo struct{ gen.DO }
|
||||
|
||||
func (a adminRoleLinkDo) Debug() *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Debug())
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) WithContext(ctx context.Context) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.WithContext(ctx))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) ReadDB() *adminRoleLinkDo {
|
||||
return a.Clauses(dbresolver.Read)
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) WriteDB() *adminRoleLinkDo {
|
||||
return a.Clauses(dbresolver.Write)
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Session(config *gorm.Session) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Session(config))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Clauses(conds ...clause.Expression) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Clauses(conds...))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Returning(value interface{}, columns ...string) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Returning(value, columns...))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Not(conds ...gen.Condition) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Not(conds...))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Or(conds ...gen.Condition) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Or(conds...))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Select(conds ...field.Expr) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Select(conds...))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Where(conds ...gen.Condition) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Where(conds...))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Order(conds ...field.Expr) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Order(conds...))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Distinct(cols ...field.Expr) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Distinct(cols...))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Omit(cols ...field.Expr) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Omit(cols...))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Join(table schema.Tabler, on ...field.Expr) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Join(table, on...))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) LeftJoin(table schema.Tabler, on ...field.Expr) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.LeftJoin(table, on...))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) RightJoin(table schema.Tabler, on ...field.Expr) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.RightJoin(table, on...))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Group(cols ...field.Expr) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Group(cols...))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Having(conds ...gen.Condition) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Having(conds...))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Limit(limit int) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Limit(limit))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Offset(offset int) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Offset(offset))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Scopes(funcs...))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Unscoped() *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Unscoped())
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Create(values ...*models.AdminRoleLink) error {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return a.DO.Create(values)
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) CreateInBatches(values []*models.AdminRoleLink, batchSize int) error {
|
||||
return a.DO.CreateInBatches(values, batchSize)
|
||||
}
|
||||
|
||||
// Save : !!! underlying implementation is different with GORM
|
||||
// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
|
||||
func (a adminRoleLinkDo) Save(values ...*models.AdminRoleLink) error {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return a.DO.Save(values)
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) First() (*models.AdminRoleLink, error) {
|
||||
if result, err := a.DO.First(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.AdminRoleLink), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Take() (*models.AdminRoleLink, error) {
|
||||
if result, err := a.DO.Take(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.AdminRoleLink), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Last() (*models.AdminRoleLink, error) {
|
||||
if result, err := a.DO.Last(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.AdminRoleLink), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Find() ([]*models.AdminRoleLink, error) {
|
||||
result, err := a.DO.Find()
|
||||
return result.([]*models.AdminRoleLink), err
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.AdminRoleLink, err error) {
|
||||
buf := make([]*models.AdminRoleLink, 0, batchSize)
|
||||
err = a.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
|
||||
defer func() { results = append(results, buf...) }()
|
||||
return fc(tx, batch)
|
||||
})
|
||||
return results, err
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) FindInBatches(result *[]*models.AdminRoleLink, batchSize int, fc func(tx gen.Dao, batch int) error) error {
|
||||
return a.DO.FindInBatches(result, batchSize, fc)
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Attrs(attrs ...field.AssignExpr) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Attrs(attrs...))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Assign(attrs ...field.AssignExpr) *adminRoleLinkDo {
|
||||
return a.withDO(a.DO.Assign(attrs...))
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Joins(fields ...field.RelationField) *adminRoleLinkDo {
|
||||
for _, _f := range fields {
|
||||
a = *a.withDO(a.DO.Joins(_f))
|
||||
}
|
||||
return &a
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Preload(fields ...field.RelationField) *adminRoleLinkDo {
|
||||
for _, _f := range fields {
|
||||
a = *a.withDO(a.DO.Preload(_f))
|
||||
}
|
||||
return &a
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) FirstOrInit() (*models.AdminRoleLink, error) {
|
||||
if result, err := a.DO.FirstOrInit(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.AdminRoleLink), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) FirstOrCreate() (*models.AdminRoleLink, error) {
|
||||
if result, err := a.DO.FirstOrCreate(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*models.AdminRoleLink), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) FindByPage(offset int, limit int) (result []*models.AdminRoleLink, count int64, err error) {
|
||||
result, err = a.Offset(offset).Limit(limit).Find()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if size := len(result); 0 < limit && 0 < size && size < limit {
|
||||
count = int64(size + offset)
|
||||
return
|
||||
}
|
||||
|
||||
count, err = a.Offset(-1).Limit(-1).Count()
|
||||
return
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
|
||||
count, err = a.Count()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = a.Offset(offset).Limit(limit).Scan(result)
|
||||
return
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Scan(result interface{}) (err error) {
|
||||
return a.DO.Scan(result)
|
||||
}
|
||||
|
||||
func (a adminRoleLinkDo) Delete(models ...*models.AdminRoleLink) (result gen.ResultInfo, err error) {
|
||||
return a.DO.Delete(models)
|
||||
}
|
||||
|
||||
func (a *adminRoleLinkDo) withDO(do gen.Dao) *adminRoleLinkDo {
|
||||
a.DO = *do.(*gen.DO)
|
||||
return a
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user