From 7f30b6be4ed88a7a381bbe3f37588655a8305b7a Mon Sep 17 00:00:00 2001 From: luorijun Date: Mon, 1 Jun 2026 16:08:58 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=A8=E6=9D=83=E9=99=90=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=20&=20=E4=BC=98=E5=8C=96=20router=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 29 +++++---- scripts/sql/fill.sql | 8 +++ web/handlers/edge.go | 149 ------------------------------------------- web/routes.go | 90 +++++++++++++------------- 4 files changed, 72 insertions(+), 204 deletions(-) delete mode 100644 web/handlers/edge.go diff --git a/README.md b/README.md index 84d0362..c8f7a7f 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ 交易信息持久化 订单关闭问题,在前端关闭窗口后直接调用了全部订单接口,应改成先确认再关闭 + - 取消订单接口改成只允许管理员调用 - 新增关闭订单接口,关闭订单的逻辑是先尝试完成,如果订单未支付则取消订单 @@ -18,27 +19,33 @@ 冷数据迁移方案 -## 开发环境 +## 开发流程 -### 更新表结构的流程 +### 新建数据表流程 -1. 编辑 `scripts/sql/init.sql` 文件,参照原有格式,需要注意: +1. 创建 model 文件 +2. 将 model 按照格式添加声明到 `cmd/gen/main.go` 中 +3. 编辑 `scripts/sql/init.sql` 文件,参照原有格式,需要注意: - 先写 drop table if exists 语句,确保脚本可以幂等执行 - - 编写 create table 语句,按需添加审计字段和软删除字段 (created_at, updated_at, deleted_at) - 为有必要的字段添加索引 - 为数据表及其字段添加注释 - 在文件末尾创建数据表流程全部结束后,为字段添加外键 -2. 建议用数据库工具检查差异并增量更新,或者手动增量更新 -3. 创建 model 文件,并将其添加到 gen 代码中 -4. 生成查询文件 +4. 调用 `go run ./cmd/gen/main.go` 生成查询文件 -### 权限管理 +### 更新数据表流程 -在 `web/core/scopes.go` 下定义了系统所有静态权限 +1. 更新 model 文件 +2. 编辑 `scripts/sql/init.sql` 文件,参照原有格式,需要注意: + - 先写 drop table if exists 语句,确保脚本可以幂等执行 + - 为有必要的字段添加索引 + - 为数据表及其字段添加注释 + - 在文件末尾创建数据表流程全部结束后,为字段添加外键 +3. 调用 `go run ./cmd/gen/main.go` 更新查询文件 -新增系统权限需要在数据库中配套添加权限 +### 新增接口或修改接口权限 -前端也需要新增配套权限定义 +1. 在 `web/core/scopes.go` 下声明权限常量。通常格式为 `Model:Action:SubAction`,例如 `User:Create`、`User:Delete`、`User:Update:Password` 等 +2. 在 `scripts/sql/fill.sql` 文件的权限区域添加或修改权限条目 ## 业务逻辑 diff --git a/scripts/sql/fill.sql b/scripts/sql/fill.sql index 833eeb0..d51ed40 100644 --- a/scripts/sql/fill.sql +++ b/scripts/sql/fill.sql @@ -239,6 +239,10 @@ insert into permission (parent_id, name, description, sort) values insert into permission (parent_id, name, description, sort) values ((select id from permission where name = 'proxy:write' and deleted_at is null), 'proxy:write:status', '更改代理状态', 1); +-- channel:write 子权限 +insert into permission (parent_id, name, description, sort) values + ((select id from permission where name = 'channel:write' and deleted_at is null), 'channel:write:clear_expired', '清理过期 IP', 1); + -- resource:short 子权限 insert into permission (parent_id, name, description, sort) values ((select id from permission where name = 'resource:short' and deleted_at is null), 'resource:short:read', '读取用户短效动态套餐列表', 1); @@ -285,6 +289,10 @@ insert into permission (parent_id, name, description, sort) values insert into permission (parent_id, name, description, sort) values ((select id from permission where name = 'coupon_user:read' and deleted_at is null), 'coupon_user:read:of_user', '读取指定用户的已发放优惠券列表', 1); +-- trade:write 子权限 +insert into permission (parent_id, name, description, sort) values + ((select id from permission where name = 'trade:write' and deleted_at is null), 'trade:write:complete', '完成交易', 1); + -- -------------------------- -- level 4 -- -------------------------- diff --git a/web/handlers/edge.go b/web/handlers/edge.go deleted file mode 100644 index 552fab4..0000000 --- a/web/handlers/edge.go +++ /dev/null @@ -1,149 +0,0 @@ -package handlers - -import ( - s "platform/web/services" - - "github.com/gofiber/fiber/v2" -) - -type RegisterEdgeReq struct { - Name string `json:"name" validate:"required"` - Version int `json:"version" validate:"required"` -} - -type RegisterEdgeResp struct { - Id int32 `json:"id"` - Host string `json:"host"` -} - -func AssignEdge(c *fiber.Ctx) (err error) { - 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 { - s.EdgeFilter - Count int `json:"count"` -} - -type AllEdgesAvailableRespItem struct { - Ip string `json:"ip"` // 节点地址 - Port int32 `json:"port"` // 代理服务端口 - Isp string `json:"isp"` // 运营商 - Prov string `json:"prov"` // 省份 - City string `json:"city"` // 城市 - Status int32 `json:"status"` // 节点状态:0-离线,1-正常 -} - -func AllEdgesAvailable(c *fiber.Ctx) (err error) { - return c.JSON(map[string]any{ - "error": "接口暂不可用", - }) - - // // 检查权限 - // _, err = auth.GetAuthCtx(c).PermitSecretClient() - // if err != nil { - // return err - // } - - // // 验证请求参数 - // var req = new(AllEdgesAvailableReq) - // err = g.Validator.Validate(c, req) - // if err != nil { - // return err - // } - - // // 获取可用的转发服务 - // 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) -} diff --git a/web/routes.go b/web/routes.go index 578ba4b..52f7ac4 100644 --- a/web/routes.go +++ b/web/routes.go @@ -15,9 +15,10 @@ import ( func ApplyRouters(app *fiber.App) { api := app.Group("/api") + publicRouter(api) + clientRouter(api) userRouter(api) adminRouter(api) - clientRouter(api) // 回调 callbacks := app.Group("/callback") @@ -52,8 +53,8 @@ func ApplyRouters(app *fiber.App) { } } -// 用户接口路由 -func userRouter(api fiber.Router) { +// 公开接口路由 +func publicRouter(api fiber.Router) { // 认证 auth := api.Group("/auth") auth.Get("/authorize", auth2.AuthorizeGet) @@ -62,6 +63,48 @@ func userRouter(api fiber.Router) { auth.Post("/revoke", auth2.Revoke) auth.Post("/introspect", auth2.Introspect) + // 套餐 + resource := api.Group("/resource") + resource.Post("/price", handlers.ResourcePrice) + + // 交易 + trade := api.Group("/trade") + trade.Get("/check", handlers.TradeCheck) + + // 前台 + inquiry := api.Group("/inquiry") + inquiry.Post("/create", handlers.CreateInquiry) + + // 产品 + product := api.Group("/product") + product.Post("/list", handlers.AllProduct) +} + +// 客户端接口路由 +func clientRouter(api fiber.Router) { + client := api + + // 验证短信令牌 + client.Post("/verify/sms", handlers.SendSmsCode) + + // 网关 + proxy := client.Group("/proxy") + proxy.Post("/online", handlers.ProxyReportOnline) + proxy.Post("/offline", handlers.ProxyReportOffline) + proxy.Post("/update", handlers.ProxyReportUpdate) + + // 通道管理 + channel := client.Group("/channel") + channel.Post("/remove", handlers.RemoveChannels) + + // 文章查看 + article := api.Group("/article") + article.Post("/nav", handlers.NavArticle) + article.Post("/get", handlers.GetArticle) +} + +// 用户接口路由 +func userRouter(api fiber.Router) { // 用户 user := api.Group("/user") user.Post("/update", handlers.UpdateUser) @@ -102,7 +145,6 @@ func userRouter(api fiber.Router) { trade.Post("/create", handlers.TradeCreate) trade.Post("/complete", handlers.TradeComplete) trade.Post("/cancel", handlers.TradeCancel) - trade.Get("/check", handlers.TradeCheck) // 账单 bill := api.Group("/bill") @@ -121,51 +163,11 @@ func userRouter(api fiber.Router) { announcement := api.Group("/announcement") announcement.Post("/list", handlers.ListAnnouncements) - // 网关 - proxy := api.Group("/proxy") - proxy.Post("/online", handlers.ProxyReportOnline) - proxy.Post("/offline", handlers.ProxyReportOffline) - proxy.Post("/update", handlers.ProxyReportUpdate) - - // 节点 - edge := api.Group("/edge") - edge.Post("/assign", handlers.AssignEdge) - edge.Post("/all", handlers.AllEdgesAvailable) - - // 前台 - inquiry := api.Group("/inquiry") - inquiry.Post("/create", handlers.CreateInquiry) - - // 产品 - product := api.Group("/product") - product.Post("/list", handlers.AllProduct) - // 认证 verify := api.Group("/verify") verify.Post("/sms/password", handlers.SendSmsCodeForPassword) } -// 客户端接口路由 -func clientRouter(api fiber.Router) { - client := api - - // 验证短信令牌 - client.Post("/verify/sms", handlers.SendSmsCode) - - // 套餐定价查询 - resource := client.Group("/resource") - resource.Post("/price", handlers.ResourcePrice) - - // 通道管理 - channel := client.Group("/channel") - channel.Post("/remove", handlers.RemoveChannels) - - // 文章查看 - article := api.Group("/article") - article.Post("/nav", handlers.NavArticle) - article.Post("/get", handlers.GetArticle) -} - // 管理员接口路由 func adminRouter(api fiber.Router) { api = api.Group("/admin")