This commit is contained in:
2026-04-25 11:59:10 +08:00
parent e246271a24
commit ba463ae38d
33 changed files with 1600 additions and 112 deletions

View File

@@ -0,0 +1,211 @@
package handlers
import (
"strconv"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
subordinate_app "tyapi-server/internal/application/subordinate"
"tyapi-server/internal/application/subordinate/dto/commands"
"tyapi-server/internal/shared/interfaces"
)
// SubordinateHandler 下属账号
type SubordinateHandler struct {
app subordinate_app.SubordinateApplicationService
response interfaces.ResponseBuilder
validator interfaces.RequestValidator
logger *zap.Logger
}
// NewSubordinateHandler 构造
func NewSubordinateHandler(
app subordinate_app.SubordinateApplicationService,
response interfaces.ResponseBuilder,
validator interfaces.RequestValidator,
logger *zap.Logger,
) *SubordinateHandler {
return &SubordinateHandler{app: app, response: response, validator: validator, logger: logger}
}
// SubPortalRegister 子站注册
func (h *SubordinateHandler) SubPortalRegister(c *gin.Context) {
var cmd commands.SubPortalRegisterCommand
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
return
}
res, err := h.app.RegisterSubPortal(c.Request.Context(), &cmd)
if err != nil {
h.logger.Error("子站注册失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
h.response.Created(c, res, "注册成功")
}
// CreateInvitation 主账号创建邀请
func (h *SubordinateHandler) CreateInvitation(c *gin.Context) {
parentID := c.GetString("user_id")
if parentID == "" {
h.response.Unauthorized(c, "未登录")
return
}
var body struct {
ExpiresInHours int `json:"expires_in_hours"`
}
_ = c.ShouldBindJSON(&body)
res, err := h.app.CreateInvitation(c.Request.Context(), &commands.CreateInvitationCommand{
ParentUserID: parentID,
ExpiresInHours: body.ExpiresInHours,
})
if err != nil {
h.logger.Error("创建邀请失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, res, "邀请已创建")
}
// ListSubordinates 下属列表
func (h *SubordinateHandler) ListSubordinates(c *gin.Context) {
parentID := c.GetString("user_id")
if parentID == "" {
h.response.Unauthorized(c, "未登录")
return
}
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
size, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
res, err := h.app.ListMySubordinates(c.Request.Context(), parentID, page, size)
if err != nil {
h.logger.Error("获取下属列表失败", zap.Error(err))
h.response.InternalError(c, "获取下属列表失败")
return
}
h.response.Success(c, res, "获取成功")
}
// Allocate 划款
func (h *SubordinateHandler) Allocate(c *gin.Context) {
parentID := c.GetString("user_id")
if parentID == "" {
h.response.Unauthorized(c, "未登录")
return
}
var cmd commands.AllocateToChildCommand
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
return
}
cmd.ParentUserID = parentID
if err := h.app.AllocateToChild(c.Request.Context(), &cmd); err != nil {
h.logger.Error("划拨失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, nil, "划拨成功")
}
// ListAllocations 下属划拨记录
func (h *SubordinateHandler) ListAllocations(c *gin.Context) {
parentID := c.GetString("user_id")
if parentID == "" {
h.response.Unauthorized(c, "未登录")
return
}
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
size, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
cmd := &commands.ListChildAllocationsCommand{
ParentUserID: parentID,
ChildUserID: c.Query("child_user_id"),
Page: page,
PageSize: size,
}
if cmd.ChildUserID == "" {
h.response.BadRequest(c, "child_user_id 不能为空")
return
}
res, err := h.app.ListChildAllocations(c.Request.Context(), cmd)
if err != nil {
h.logger.Error("获取划拨记录失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, res, "获取成功")
}
// AssignSubscription 代配订阅
func (h *SubordinateHandler) AssignSubscription(c *gin.Context) {
parentID := c.GetString("user_id")
if parentID == "" {
h.response.Unauthorized(c, "未登录")
return
}
var cmd commands.AssignChildSubscriptionCommand
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
return
}
cmd.ParentUserID = parentID
if err := h.app.AssignChildSubscription(c.Request.Context(), &cmd); err != nil {
h.logger.Error("代配订阅失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, nil, "已保存下属订阅")
}
// ListChildSubscriptions 下属订阅列表
func (h *SubordinateHandler) ListChildSubscriptions(c *gin.Context) {
parentID := c.GetString("user_id")
if parentID == "" {
h.response.Unauthorized(c, "未登录")
return
}
childID := c.Query("child_user_id")
if childID == "" {
h.response.BadRequest(c, "child_user_id 不能为空")
return
}
res, err := h.app.ListChildSubscriptions(c.Request.Context(), &commands.ListChildSubscriptionsCommand{
ParentUserID: parentID,
ChildUserID: childID,
})
if err != nil {
h.logger.Error("获取下属订阅失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, res, "获取成功")
}
// RemoveChildSubscription 删除下属订阅
func (h *SubordinateHandler) RemoveChildSubscription(c *gin.Context) {
parentID := c.GetString("user_id")
if parentID == "" {
h.response.Unauthorized(c, "未登录")
return
}
var body struct {
ChildUserID string `json:"child_user_id"`
}
_ = c.ShouldBindJSON(&body)
if body.ChildUserID == "" {
h.response.BadRequest(c, "child_user_id 不能为空")
return
}
subID := c.Param("subscription_id")
if subID == "" {
h.response.BadRequest(c, "subscription_id 不能为空")
return
}
err := h.app.RemoveChildSubscription(c.Request.Context(), &commands.RemoveChildSubscriptionCommand{
ParentUserID: parentID,
ChildUserID: body.ChildUserID,
SubscriptionID: subID,
})
if err != nil {
h.logger.Error("删除下属订阅失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, nil, "删除成功")
}

View File

@@ -49,8 +49,6 @@ func (r *CertificationRoutes) Register(router *http.GinRouter) {
authGroup := certificationGroup.Group("")
authGroup.Use(r.auth.Handle())
{
authGroup.GET("", r.handler.ListCertifications) // 查询认证列表(管理员)
// 1. 获取认证详情
authGroup.GET("/details", r.handler.GetCertification)
@@ -71,10 +69,6 @@ func (r *CertificationRoutes) Register(router *http.GinRouter) {
// 前端确认是否完成签署
authGroup.POST("/confirm-sign", r.handler.ConfirmSign)
// 管理员代用户完成认证(暂不关联合同)
authGroup.POST("/admin/complete-without-contract", r.handler.AdminCompleteCertificationWithoutContract)
}
// 管理端企业审核(需管理员权限,以状态机状态为准)
@@ -82,6 +76,8 @@ func (r *CertificationRoutes) Register(router *http.GinRouter) {
adminGroup.Use(r.auth.Handle())
adminGroup.Use(r.admin.Handle())
{
adminGroup.GET("", r.handler.ListCertifications) // 查询认证列表(管理员)
adminGroup.POST("/complete-without-contract", r.handler.AdminCompleteCertificationWithoutContract)
adminGroup.POST("/transition-status", r.handler.AdminTransitionCertificationStatus)
}
adminCertGroup := adminGroup.Group("/submit-records")

View File

@@ -0,0 +1,46 @@
package routes
import (
"tyapi-server/internal/infrastructure/http/handlers"
sharedhttp "tyapi-server/internal/shared/http"
"tyapi-server/internal/shared/middleware"
"go.uber.org/zap"
)
// SubordinateRoutes 下属与邀请路由
type SubordinateRoutes struct {
handler *handlers.SubordinateHandler
auth *middleware.JWTAuthMiddleware
logger *zap.Logger
}
// NewSubordinateRoutes 构造
func NewSubordinateRoutes(
handler *handlers.SubordinateHandler,
auth *middleware.JWTAuthMiddleware,
logger *zap.Logger,
) *SubordinateRoutes {
return &SubordinateRoutes{handler: handler, auth: auth, logger: logger}
}
// Register 注册
func (r *SubordinateRoutes) Register(router *sharedhttp.GinRouter) {
g := router.GetEngine()
g.POST("/api/v1/sub-portal/register", r.handler.SubPortalRegister)
sub := g.Group("/api/v1/subordinate")
sub.Use(r.auth.Handle())
{
sub.POST("/invitations", r.handler.CreateInvitation)
sub.GET("/subordinates", r.handler.ListSubordinates)
sub.POST("/allocate", r.handler.Allocate)
sub.GET("/allocations", r.handler.ListAllocations)
sub.POST("/assign-subscription", r.handler.AssignSubscription)
sub.GET("/child-subscriptions", r.handler.ListChildSubscriptions)
sub.DELETE("/child-subscriptions/:subscription_id", r.handler.RemoveChildSubscription)
}
r.logger.Info("下属账号路由注册完成")
}