feat: add TenantDetail and UserDetail views with comprehensive functionality
- Implemented TenantDetail.vue to display tenant information, manage tenant status, and handle tenant renewals. - Added user management features in UserDetail.vue, including user status updates and role management. - Integrated data loading for tenant users and orders in TenantDetail.vue. - Included search and pagination functionalities for owned and joined tenants in UserDetail.vue. - Enhanced user experience with toast notifications for success and error messages.
This commit is contained in:
@@ -82,6 +82,11 @@ func (r *Routes) Register(router fiber.Router) {
|
||||
r.tenant.list,
|
||||
Query[dto.TenantFilter]("filter"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Get /super/v1/tenants/:tenantID<int> -> tenant.detail")
|
||||
router.Get("/super/v1/tenants/:tenantID<int>"[len(r.Path()):], DataFunc1(
|
||||
r.tenant.detail,
|
||||
PathParam[int64]("tenantID"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Get /super/v1/tenants/:tenantID<int>/users -> tenant.users")
|
||||
router.Get("/super/v1/tenants/:tenantID<int>/users"[len(r.Path()):], DataFunc2(
|
||||
r.tenant.users,
|
||||
@@ -115,6 +120,11 @@ func (r *Routes) Register(router fiber.Router) {
|
||||
r.user.list,
|
||||
Query[dto.UserPageFilter]("filter"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Get /super/v1/users/:userID<int> -> user.detail")
|
||||
router.Get("/super/v1/users/:userID<int>"[len(r.Path()):], DataFunc1(
|
||||
r.user.detail,
|
||||
PathParam[int64]("userID"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Get /super/v1/users/:userID<int>/tenants -> user.tenants")
|
||||
router.Get("/super/v1/users/:userID<int>/tenants"[len(r.Path()):], DataFunc2(
|
||||
r.user.tenants,
|
||||
|
||||
@@ -15,6 +15,21 @@ import (
|
||||
// @provider
|
||||
type tenant struct{}
|
||||
|
||||
// detail
|
||||
//
|
||||
// @Summary 租户详情
|
||||
// @Tags Super
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param tenantID path int64 true "TenantID"
|
||||
// @Success 200 {object} dto.TenantItem
|
||||
//
|
||||
// @Router /super/v1/tenants/:tenantID<int> [get]
|
||||
// @Bind tenantID path
|
||||
func (*tenant) detail(ctx fiber.Ctx, tenantID int64) (*dto.TenantItem, error) {
|
||||
return services.Tenant.SuperDetail(ctx, tenantID)
|
||||
}
|
||||
|
||||
// list
|
||||
//
|
||||
// @Summary 租户列表
|
||||
|
||||
@@ -13,6 +13,21 @@ import (
|
||||
// @provider
|
||||
type user struct{}
|
||||
|
||||
// detail
|
||||
//
|
||||
// @Summary 用户详情
|
||||
// @Tags Super
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param userID path int64 true "UserID"
|
||||
// @Success 200 {object} dto.UserItem
|
||||
//
|
||||
// @Router /super/v1/users/:userID<int> [get]
|
||||
// @Bind userID path
|
||||
func (*user) detail(ctx fiber.Ctx, userID int64) (*dto.UserItem, error) {
|
||||
return services.User.Detail(ctx, userID)
|
||||
}
|
||||
|
||||
// list
|
||||
//
|
||||
// @Summary 用户列表
|
||||
|
||||
@@ -26,6 +26,49 @@ import (
|
||||
// @provider
|
||||
type tenant struct{}
|
||||
|
||||
// SuperDetail 查询单个租户详情(平台侧)。
|
||||
func (t *tenant) SuperDetail(ctx context.Context, tenantID int64) (*superdto.TenantItem, error) {
|
||||
if tenantID <= 0 {
|
||||
return nil, errors.New("tenant_id must be > 0")
|
||||
}
|
||||
|
||||
tbl, query := models.TenantQuery.QueryContext(ctx)
|
||||
m, err := query.Where(tbl.ID.Eq(tenantID)).First()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userCountMapping, err := t.TenantUserCountMapping(ctx, []int64{m.ID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
incomeMapping, err := t.TenantIncomePaidMapping(ctx, []int64{m.ID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
item := &superdto.TenantItem{
|
||||
Tenant: m,
|
||||
UserCount: lo.ValueOr(userCountMapping, m.ID, 0),
|
||||
IncomeAmountPaidSum: lo.ValueOr(incomeMapping, m.ID, 0),
|
||||
StatusDescription: m.Status.Description(),
|
||||
}
|
||||
|
||||
ownerMapping, err := t.TenantOwnerUserMapping(ctx, []*models.Tenant{m})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
item.Owner = ownerMapping[m.ID]
|
||||
|
||||
adminMapping, err := t.TenantAdminUsersMapping(ctx, []int64{m.ID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
item.AdminUsers = adminMapping[m.ID]
|
||||
|
||||
return item, nil
|
||||
}
|
||||
|
||||
// SuperCreateTenant 超级管理员创建租户,并将指定用户设为租户管理员。
|
||||
func (t *tenant) SuperCreateTenant(ctx context.Context, form *superdto.TenantCreateForm) (*models.Tenant, error) {
|
||||
if form == nil {
|
||||
|
||||
@@ -41,6 +41,42 @@ func (t *user) FindByUsername(ctx context.Context, username string) (*models.Use
|
||||
return model, nil
|
||||
}
|
||||
|
||||
// Detail 查询用户详情(超级管理员侧,返回脱敏后的 DTO)。
|
||||
func (t *user) Detail(ctx context.Context, userID int64) (*dto.UserItem, error) {
|
||||
if userID <= 0 {
|
||||
return nil, errors.New("user_id must be > 0")
|
||||
}
|
||||
|
||||
model, err := t.FindByID(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ownedTenantCounts, err := t.UserOwnedTenantCountMapping(ctx, []int64{model.ID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
joinedTenantCounts, err := t.UserJoinedTenantCountMapping(ctx, []int64{model.ID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &dto.UserItem{
|
||||
ID: model.ID,
|
||||
Username: model.Username,
|
||||
Roles: model.Roles,
|
||||
Status: model.Status,
|
||||
StatusDescription: model.Status.Description(),
|
||||
Balance: model.Balance,
|
||||
BalanceFrozen: model.BalanceFrozen,
|
||||
VerifiedAt: model.VerifiedAt,
|
||||
CreatedAt: model.CreatedAt,
|
||||
UpdatedAt: model.UpdatedAt,
|
||||
OwnedTenantCount: ownedTenantCounts[model.ID],
|
||||
JoinedTenantCount: joinedTenantCounts[model.ID],
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (t *user) Create(ctx context.Context, user *models.User) (*models.User, error) {
|
||||
if err := user.Create(ctx); err != nil {
|
||||
return nil, errors.Wrapf(err, "Create user failed, %s", user.Username)
|
||||
|
||||
Reference in New Issue
Block a user