From bc39021c0d92ae4a2d28a142f41b9f5a22eca5d3 Mon Sep 17 00:00:00 2001 From: david Date: Tue, 28 Jul 2026 13:35:59 +0800 Subject: [PATCH] refactor platform account and access models --- backend/api/internal/initdb/platform.go | 6 +- backend/api/internal/initdb/platform_test.go | 2 +- .../internal/logic/common/platform_access.go | 41 +++++ backend/api/internal/logic/common/resource.go | 2 +- backend/api/internal/logic/platform/auth.go | 9 +- ...m_menu_platfrom_account.go => platform.go} | 164 ++++++++++++++---- .../logic/platform/platform_access.go | 112 ------------ .../logic/platform/product_workflow.go | 2 +- .../logic/platform/resource_contract.go | 2 +- .../logic/platform/wallet_workflow.go | 6 +- ...latfrom_account.go => platform_account.go} | 8 +- .../internal/models/platform_models_test.go | 23 +++ ...menu_relation.go => platform_role_menu.go} | 8 +- backend/api/internal/models/query.go | 8 +- backend/api/internal/routers/platform.go | 9 +- backend/api/internal/routers/platform_test.go | 5 +- frontend/platform_admin/src/api/platform.ts | 2 +- frontend/platform_admin/src/api/resources.ts | 2 +- .../src/contracts/platform-resources.json | 2 +- .../src/router/routes/modules/platform.ts | 2 +- 20 files changed, 234 insertions(+), 181 deletions(-) create mode 100644 backend/api/internal/logic/common/platform_access.go rename backend/api/internal/logic/platform/{platform_role_platform_menu_platfrom_account.go => platform.go} (75%) delete mode 100644 backend/api/internal/logic/platform/platform_access.go rename backend/api/internal/models/{platfrom_account.go => platform_account.go} (81%) create mode 100644 backend/api/internal/models/platform_models_test.go rename backend/api/internal/models/{platform_role_menu_relation.go => platform_role_menu.go} (70%) diff --git a/backend/api/internal/initdb/platform.go b/backend/api/internal/initdb/platform.go index 67903b5..16414ec 100644 --- a/backend/api/internal/initdb/platform.go +++ b/backend/api/internal/initdb/platform.go @@ -50,7 +50,7 @@ func InitPlatformAccess(database *gorm.DB) error { if err := database.Where("menu_code = ?", menu.MenuCode).FirstOrCreate(&menu).Error; err != nil { return err } - relation := models.PlatformRoleMenuRelation{PlatformRoleID: rootRole.ID, PlatformMenuID: menu.ID} + relation := models.PlatformRoleMenu{PlatformRoleID: rootRole.ID, PlatformMenuID: menu.ID} if err := database.Where("platform_role_id = ? AND platform_menu_id = ?", rootRole.ID, menu.ID).FirstOrCreate(&relation).Error; err != nil { return err } @@ -60,7 +60,7 @@ func InitPlatformAccess(database *gorm.DB) error { // InitPlatformRoot 幂等创建平台总后台 root 账号。 func InitPlatformRoot(database *gorm.DB) error { - var account models.PlatfromAccount + var account models.PlatformAccount err := database.Where("username = ?", PlatformRootUsername).First(&account).Error if err == nil { return nil @@ -74,7 +74,7 @@ func InitPlatformRoot(database *gorm.DB) error { return err } - account = models.PlatfromAccount{ + account = models.PlatformAccount{ Entity: models.Entity{Identity: models.NewIdentity(), Status: "enabled"}, Username: PlatformRootUsername, DisplayName: "平台根管理员", diff --git a/backend/api/internal/initdb/platform_test.go b/backend/api/internal/initdb/platform_test.go index 2eb6e68..d58db56 100644 --- a/backend/api/internal/initdb/platform_test.go +++ b/backend/api/internal/initdb/platform_test.go @@ -35,7 +35,7 @@ func TestInitPlatformAccessSeedsEveryProtectedFrontendDomain(t *testing.T) { WithArgs(domain, 1). WillReturnRows(sqlmock.NewRows([]string{"id", "identity", "status", "version", "parent_id", "menu_code", "name", "icon", "path", "sort_no"}). AddRow(menuID, domain+"-menu", "enabled", 1, uint64(0), domain, domain, "", "/"+domain, index)) - mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "platform_role_menu_relation" WHERE platform_role_id = $1 AND platform_menu_id = $2 ORDER BY "platform_role_menu_relation"."id" LIMIT $3`)). + mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "platform_role_menu" WHERE platform_role_id = $1 AND platform_menu_id = $2 ORDER BY "platform_role_menu"."id" LIMIT $3`)). WithArgs(uint64(1), menuID, 1). WillReturnRows(sqlmock.NewRows([]string{"id", "platform_role_id", "platform_menu_id"}). AddRow(uint64(index+100), uint64(1), menuID)) diff --git a/backend/api/internal/logic/common/platform_access.go b/backend/api/internal/logic/common/platform_access.go new file mode 100644 index 0000000..a7ff261 --- /dev/null +++ b/backend/api/internal/logic/common/platform_access.go @@ -0,0 +1,41 @@ +package common + +import ( + "git.apinb.com/bsm-sdk/core/errcode" + "git.apinb.com/bsm-sdk/core/infra" + "git.apinb.com/bsm-sdk/core/middleware" + "git.apinb.com/heqiapp/platforms/backend/api/internal/impl" + "git.apinb.com/heqiapp/platforms/backend/api/internal/models" + "github.com/gin-gonic/gin" +) + +// RequirePlatformRoot restricts sensitive platform configuration operations to the root role. +func RequirePlatformRoot(ctx *gin.Context) bool { + claims, err := middleware.ParseAuth(ctx) + if err == nil && claims.Role == "root" { + return true + } + infra.Response.Error(ctx, errcode.ErrPermissionDenied) + return false +} + +// LoadPlatformMenus returns the menus granted to one platform role. +func LoadPlatformMenus(roleCode string) ([]models.PlatformMenu, error) { + var menus []models.PlatformMenu + if roleCode == "root" { + err := impl.DBService.Order("sort_no asc, id asc").Find(&menus).Error + return menus, err + } + + var role models.PlatformRole + if err := impl.DBService.Where("role_code = ? AND status = ?", roleCode, "enabled").First(&role).Error; err != nil { + return nil, err + } + err := impl.DBService. + Select("platform_menu.*"). + Joins("JOIN platform_role_menu ON platform_role_menu.platform_menu_id = platform_menu.id"). + Where("platform_role_menu.platform_role_id = ? AND platform_menu.status = ?", role.ID, "enabled"). + Order("sort_no asc, id asc"). + Find(&menus).Error + return menus, err +} diff --git a/backend/api/internal/logic/common/resource.go b/backend/api/internal/logic/common/resource.go index a7e7303..f34217a 100644 --- a/backend/api/internal/logic/common/resource.go +++ b/backend/api/internal/logic/common/resource.go @@ -133,7 +133,7 @@ func isCreatedResponseField(key string) bool { func ProtectPreciseLocation(ctx *gin.Context, model, value any) any { maskPersonalName := reflect.TypeOf(model) == reflect.TypeOf(&models.UserAccount{}) || reflect.TypeOf(model) == reflect.TypeOf(&models.StaffAccount{}) - maskDisplayName := reflect.TypeOf(model) == reflect.TypeOf(&models.PlatfromAccount{}) + maskDisplayName := reflect.TypeOf(model) == reflect.TypeOf(&models.PlatformAccount{}) ProtectPublicFields(value, maskPersonalName, maskDisplayName, HasPreciseLocationScope(ctx)) return value } diff --git a/backend/api/internal/logic/platform/auth.go b/backend/api/internal/logic/platform/auth.go index 36e6b16..0a8b041 100644 --- a/backend/api/internal/logic/platform/auth.go +++ b/backend/api/internal/logic/platform/auth.go @@ -9,6 +9,7 @@ import ( "git.apinb.com/bsm-sdk/core/infra" "git.apinb.com/bsm-sdk/core/middleware" "git.apinb.com/heqiapp/platforms/backend/api/internal/impl" + "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common" "git.apinb.com/heqiapp/platforms/backend/api/internal/models" "github.com/gin-gonic/gin" "golang.org/x/crypto/bcrypt" @@ -38,7 +39,7 @@ func Login(ctx *gin.Context) { return } - var account models.PlatfromAccount + var account models.PlatformAccount err := impl.DBService.Where("username = ?", strings.TrimSpace(request.Username)).First(&account).Error if err != nil { if err == gorm.ErrRecordNotFound { @@ -85,12 +86,12 @@ func CurrentProfile(ctx *gin.Context) { infra.Response.Error(ctx, err) return } - var account models.PlatfromAccount + var account models.PlatformAccount if err := impl.DBService.Where("identity = ?", claims.Identity).First(&account).Error; err != nil { infra.Response.Error(ctx, errcode.ErrRecordNotFound) return } - menus, err := loadPlatformMenus(account.PlatformRoleCode) + menus, err := common.LoadPlatformMenus(account.PlatformRoleCode) if err != nil { infra.Response.Error(ctx, errcode.ErrPermissionDenied) return @@ -133,7 +134,7 @@ func ChangePassword(ctx *gin.Context) { infra.Response.Error(ctx, errcode.ErrInvalidArgument) return } - var account models.PlatfromAccount + var account models.PlatformAccount if err := impl.DBService.Where("identity = ?", claims.Identity).First(&account).Error; err != nil { infra.Response.Error(ctx, errcode.ErrRecordNotFound) return diff --git a/backend/api/internal/logic/platform/platform_role_platform_menu_platfrom_account.go b/backend/api/internal/logic/platform/platform.go similarity index 75% rename from backend/api/internal/logic/platform/platform_role_platform_menu_platfrom_account.go rename to backend/api/internal/logic/platform/platform.go index fa34966..2c819d3 100644 --- a/backend/api/internal/logic/platform/platform_role_platform_menu_platfrom_account.go +++ b/backend/api/internal/logic/platform/platform.go @@ -2,6 +2,7 @@ package platform import ( "errors" + "strings" "git.apinb.com/bsm-sdk/core/errcode" "git.apinb.com/bsm-sdk/core/infra" @@ -10,11 +11,83 @@ import ( "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common" "git.apinb.com/heqiapp/platforms/backend/api/internal/models" "github.com/gin-gonic/gin" + "golang.org/x/crypto/bcrypt" "gorm.io/gorm" ) var errSystemPlatformRole = errors.New("system platform roles cannot be modified") +const platformMenusContextKey = "platform_authorized_menus" + +func platformMenuAllowsPath(menus []models.PlatformMenu, requestPath string) bool { + marker := "/platform/v1/" + index := strings.Index(requestPath, marker) + if index < 0 { + return false + } + relative := strings.Trim(requestPath[index+len(marker):], "/") + resource := strings.Split(relative, "/")[0] + domain := platformRouteDomain(resource) + for _, menu := range menus { + if menu.MenuCode == domain { + return true + } + menuPath := strings.Trim(menu.Path, "/") + if menuPath != "" && strings.Split(menuPath, "/")[0] == domain { + return true + } + } + return false +} + +func platformRouteDomain(resource string) string { + prefix := strings.Split(resource, "_")[0] + switch prefix { + case "product": + return "device" + case "gasorder": + return "delivery" + case "fin": + return "finance" + case "cms": + return "content" + case "cs": + return "customer_service" + case "platform": + return "platform" + default: + return prefix + } +} + +// RequirePlatformMenuAccess enforces role-menu authorization after JWT authentication. +func RequirePlatformMenuAccess() gin.HandlerFunc { + return func(ctx *gin.Context) { + if strings.Contains(ctx.Request.URL.Path, "/platform/v1/auth/") { + ctx.Next() + return + } + claims, err := middleware.ParseAuth(ctx) + if err != nil { + infra.Response.Error(ctx, err) + ctx.Abort() + return + } + if claims.Role == "root" { + ctx.Next() + return + } + menus, err := common.LoadPlatformMenus(claims.Role) + if err != nil || !platformMenuAllowsPath(menus, ctx.Request.URL.Path) { + infra.Response.Error(ctx, errcode.ErrPermissionDenied) + ctx.Abort() + return + } + ctx.Set(platformMenusContextKey, menus) + ctx.Next() + } +} + // ListPlatformRole 查询平台角色分页列表。 func ListPlatformRole(ctx *gin.Context) { common.ListPage[models.PlatformRole](ctx) } @@ -23,7 +96,7 @@ func GetPlatformRole(ctx *gin.Context) { common.GetByIdentity[models.PlatformRol // CreatePlatformRole 创建非内置平台角色。 func CreatePlatformRole(ctx *gin.Context) { - if !requirePlatformRoot(ctx) { + if !common.RequirePlatformRoot(ctx) { return } var request models.PlatformRole @@ -45,7 +118,7 @@ func CreatePlatformRole(ctx *gin.Context) { // UpdatePlatformRole 更新非内置平台角色。 func UpdatePlatformRole(ctx *gin.Context) { - if !requirePlatformRoot(ctx) { + if !common.RequirePlatformRoot(ctx) { return } var request struct { @@ -118,7 +191,7 @@ func GetPlatformMenu(ctx *gin.Context) { } func CreatePlatformMenu(ctx *gin.Context) { - if !requirePlatformRoot(ctx) { + if !common.RequirePlatformRoot(ctx) { return } var request platformMenuRequest @@ -140,7 +213,7 @@ func CreatePlatformMenu(ctx *gin.Context) { } func UpdatePlatformMenu(ctx *gin.Context) { - if !requirePlatformRoot(ctx) { + if !common.RequirePlatformRoot(ctx) { return } var request platformMenuRequest @@ -157,14 +230,14 @@ func UpdatePlatformMenu(ctx *gin.Context) { } func UpdatePlatformMenuStatus(ctx *gin.Context) { - if !requirePlatformRoot(ctx) { + if !common.RequirePlatformRoot(ctx) { return } common.UpdateRecordStatus(ctx, &models.PlatformMenu{}) } func ArchivePlatformMenu(ctx *gin.Context) { - if !requirePlatformRoot(ctx) { + if !common.RequirePlatformRoot(ctx) { return } common.ArchiveRecord(ctx, &models.PlatformMenu{}) @@ -176,7 +249,7 @@ type platformRoleMenusRequest struct { // ReplacePlatformRoleMenus replaces every menu assignment for a role atomically. func ReplacePlatformRoleMenus(ctx *gin.Context) { - if !requirePlatformRoot(ctx) { + if !common.RequirePlatformRoot(ctx) { return } var request platformRoleMenusRequest @@ -201,11 +274,11 @@ func ReplacePlatformRoleMenus(ctx *gin.Context) { return gorm.ErrRecordNotFound } } - if err := transaction.Where("platform_role_id = ?", role.ID).Delete(&models.PlatformRoleMenuRelation{}).Error; err != nil { + if err := transaction.Where("platform_role_id = ?", role.ID).Delete(&models.PlatformRoleMenu{}).Error; err != nil { return err } for _, menu := range menus { - relation := models.PlatformRoleMenuRelation{PlatformRoleID: role.ID, PlatformMenuID: menu.ID} + relation := models.PlatformRoleMenu{PlatformRoleID: role.ID, PlatformMenuID: menu.ID} if err := transaction.Create(&relation).Error; err != nil { return err } @@ -228,7 +301,7 @@ func ReplacePlatformRoleMenus(ctx *gin.Context) { // ListPlatformRoleMenuIdentities returns the current assignment for the role editor. func ListPlatformRoleMenuIdentities(ctx *gin.Context) { - if !requirePlatformRoot(ctx) { + if !common.RequirePlatformRoot(ctx) { return } var role models.PlatformRole @@ -238,8 +311,8 @@ func ListPlatformRoleMenuIdentities(ctx *gin.Context) { } var identities []string if err := impl.DBService.Model(&models.PlatformMenu{}). - Joins("JOIN platform_role_menu_relation ON platform_role_menu_relation.platform_menu_id = platform_menu.id"). - Where("platform_role_menu_relation.platform_role_id = ?", role.ID). + Joins("JOIN platform_role_menu ON platform_role_menu.platform_menu_id = platform_menu.id"). + Where("platform_role_menu.platform_role_id = ?", role.ID). Order("platform_menu.sort_no asc, platform_menu.id asc"). Pluck("platform_menu.identity", &identities).Error; err != nil { infra.Response.Error(ctx, err) @@ -250,7 +323,7 @@ func ListPlatformRoleMenuIdentities(ctx *gin.Context) { // UpdatePlatformRoleStatus 更新非内置平台角色状态,系统角色始终受保护。 func UpdatePlatformRoleStatus(ctx *gin.Context) { - if !requirePlatformRoot(ctx) { + if !common.RequirePlatformRoot(ctx) { return } var request struct { @@ -274,7 +347,7 @@ func UpdatePlatformRoleStatus(ctx *gin.Context) { // ArchivePlatformRole 归档非内置平台角色,系统角色始终受保护。 func ArchivePlatformRole(ctx *gin.Context) { - if !requirePlatformRoot(ctx) { + if !common.RequirePlatformRoot(ctx) { return } var role models.PlatformRole @@ -286,7 +359,7 @@ func ArchivePlatformRole(ctx *gin.Context) { infra.Response.Error(ctx, errcode.ErrInvalidArgument) return } - common.UpdateAllowedByIdentity(ctx, &models.PlatformRole{}, archiveValues(), []string{"status"}) + common.UpdateAllowedByIdentity(ctx, &models.PlatformRole{}, gin.H{"status": "archived"}, []string{"status"}) } // ListPlatformMenu 返回菜单树构建所需的有序菜单列表。 @@ -296,7 +369,7 @@ func ListPlatformMenu(ctx *gin.Context) { infra.Response.Error(ctx, err) return } - list, err := loadPlatformMenus(claims.Role) + list, err := common.LoadPlatformMenus(claims.Role) if err != nil { infra.Response.Error(ctx, err) return @@ -304,12 +377,12 @@ func ListPlatformMenu(ctx *gin.Context) { infra.Response.Success(ctx, gin.H{"total": len(list), "list": platformMenuViews(list)}) } -// ListPlatfromAccount 查询平台账号列表,手机号在展示层脱敏。 -func ListPlatfromAccount(ctx *gin.Context) { +// ListPlatformAccount 查询平台账号列表,手机号在展示层脱敏。 +func ListPlatformAccount(ctx *gin.Context) { page, size := common.PageSize(ctx) - var list []models.PlatfromAccount + var list []models.PlatformAccount var total int64 - query := common.ApplyKeywordFilter(ctx, impl.DBService.Model(&models.PlatfromAccount{}), &models.PlatfromAccount{}) + query := common.ApplyKeywordFilter(ctx, impl.DBService.Model(&models.PlatformAccount{}), &models.PlatformAccount{}) if err := query.Count(&total).Error; err != nil { infra.Response.Error(ctx, err) return @@ -321,13 +394,13 @@ func ListPlatfromAccount(ctx *gin.Context) { views := make([]map[string]any, 0, len(list)) for _, item := range list { view := platformAccountView(item) - common.ProtectPreciseLocation(ctx, &models.PlatfromAccount{}, view) + common.ProtectPreciseLocation(ctx, &models.PlatformAccount{}, view) views = append(views, view) } infra.Response.Success(ctx, gin.H{"total": total, "list": views}) } -type platfromAccountRequest struct { +type platformAccountRequest struct { Username string `json:"username" binding:"required,max=64"` Password string `json:"password" binding:"required,min=8,max=128"` DisplayName string `json:"display_name" binding:"max=64"` @@ -336,7 +409,7 @@ type platfromAccountRequest struct { Phone string `json:"phone" binding:"max=32"` } -func platformAccountView(account models.PlatfromAccount) map[string]any { +func platformAccountView(account models.PlatformAccount) map[string]any { return map[string]any{ "identity": account.Identity, "username": account.Username, "display_name": account.DisplayName, "avatar": account.Avatar, "phone": account.Phone, @@ -344,21 +417,21 @@ func platformAccountView(account models.PlatfromAccount) map[string]any { } } -func GetPlatfromAccount(ctx *gin.Context) { - var account models.PlatfromAccount +func GetPlatformAccount(ctx *gin.Context) { + var account models.PlatformAccount if err := impl.DBService.Where("identity = ?", ctx.Param("identity")).First(&account).Error; err != nil { common.RespondRecordError(ctx, err) return } view := platformAccountView(account) - infra.Response.Success(ctx, common.ProtectPreciseLocation(ctx, &models.PlatfromAccount{}, view)) + infra.Response.Success(ctx, common.ProtectPreciseLocation(ctx, &models.PlatformAccount{}, view)) } -func CreatePlatfromAccount(ctx *gin.Context) { - if !requirePlatformRoot(ctx) { +func CreatePlatformAccount(ctx *gin.Context) { + if !common.RequirePlatformRoot(ctx) { return } - var request platfromAccountRequest + var request platformAccountRequest if err := ctx.ShouldBindJSON(&request); err != nil { infra.Response.Error(ctx, errcode.ErrInvalidArgument) return @@ -367,21 +440,21 @@ func CreatePlatfromAccount(ctx *gin.Context) { infra.Response.Error(ctx, errcode.ErrInvalidArgument) return } - hash, err := passwordHash(request.Password) + hash, err := platformPasswordHash(request.Password) if err != nil { infra.Response.Error(ctx, err) return } - account := models.PlatfromAccount{Entity: common.NewEntity("enabled"), Username: request.Username, DisplayName: request.DisplayName, Avatar: request.Avatar, PasswordHash: hash, PlatformRoleCode: request.PlatformRoleCode, Phone: request.Phone} + account := models.PlatformAccount{Entity: common.NewEntity("enabled"), Username: request.Username, DisplayName: request.DisplayName, Avatar: request.Avatar, PasswordHash: hash, PlatformRoleCode: request.PlatformRoleCode, Phone: request.Phone} if err := impl.DBService.Create(&account).Error; err != nil { infra.Response.Error(ctx, err) return } view := platformAccountView(account) - infra.Response.Success(ctx, common.ProtectPreciseLocation(ctx, &models.PlatfromAccount{}, view)) + infra.Response.Success(ctx, common.ProtectPreciseLocation(ctx, &models.PlatformAccount{}, view)) } -func UpdatePlatfromAccount(ctx *gin.Context) { +func UpdatePlatformAccount(ctx *gin.Context) { var request struct { DisplayName string `json:"display_name" binding:"max=64"` Avatar string `json:"avatar" binding:"max=512"` @@ -394,7 +467,7 @@ func UpdatePlatfromAccount(ctx *gin.Context) { } values := gin.H{"display_name": request.DisplayName, "avatar": request.Avatar, "phone": request.Phone} if request.PlatformRoleCode != nil { - if !requirePlatformRoot(ctx) { + if !common.RequirePlatformRoot(ctx) { return } if !isAssignablePlatformRole(*request.PlatformRoleCode) { @@ -403,7 +476,28 @@ func UpdatePlatfromAccount(ctx *gin.Context) { } values["platform_role_code"] = *request.PlatformRoleCode } - common.UpdateAllowedByIdentity(ctx, &models.PlatfromAccount{}, values, []string{"display_name", "avatar", "platform_role_code", "phone"}) + common.UpdateAllowedByIdentity(ctx, &models.PlatformAccount{}, values, []string{"display_name", "avatar", "platform_role_code", "phone"}) +} + +// UpdatePlatformAccountStatus updates a platform account lifecycle state. +func UpdatePlatformAccountStatus(ctx *gin.Context) { + if !common.RequirePlatformRoot(ctx) { + return + } + common.UpdateRecordStatus(ctx, &models.PlatformAccount{}) +} + +// ArchivePlatformAccount archives a platform account without deleting audit history. +func ArchivePlatformAccount(ctx *gin.Context) { + if !common.RequirePlatformRoot(ctx) { + return + } + common.ArchiveRecord(ctx, &models.PlatformAccount{}) +} + +func platformPasswordHash(password string) (string, error) { + hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + return string(hash), err } func isAssignablePlatformRole(roleCode string) bool { diff --git a/backend/api/internal/logic/platform/platform_access.go b/backend/api/internal/logic/platform/platform_access.go deleted file mode 100644 index d8d27e1..0000000 --- a/backend/api/internal/logic/platform/platform_access.go +++ /dev/null @@ -1,112 +0,0 @@ -package platform - -import ( - "strings" - - "git.apinb.com/bsm-sdk/core/errcode" - "git.apinb.com/bsm-sdk/core/infra" - "git.apinb.com/bsm-sdk/core/middleware" - "git.apinb.com/heqiapp/platforms/backend/api/internal/impl" - "git.apinb.com/heqiapp/platforms/backend/api/internal/models" - "github.com/gin-gonic/gin" -) - -const platformMenusContextKey = "platform_authorized_menus" - -func loadPlatformMenus(roleCode string) ([]models.PlatformMenu, error) { - var menus []models.PlatformMenu - if roleCode == "root" { - err := impl.DBService.Order("sort_no asc, id asc").Find(&menus).Error - return menus, err - } - - var role models.PlatformRole - if err := impl.DBService.Where("role_code = ? AND status = ?", roleCode, "enabled").First(&role).Error; err != nil { - return nil, err - } - err := impl.DBService. - Select("platform_menu.*"). - Joins("JOIN platform_role_menu_relation ON platform_role_menu_relation.platform_menu_id = platform_menu.id"). - Where("platform_role_menu_relation.platform_role_id = ? AND platform_menu.status = ?", role.ID, "enabled"). - Order("sort_no asc, id asc"). - Find(&menus).Error - return menus, err -} - -func platformMenuAllowsPath(menus []models.PlatformMenu, requestPath string) bool { - marker := "/platform/v1/" - index := strings.Index(requestPath, marker) - if index < 0 { - return false - } - relative := strings.Trim(requestPath[index+len(marker):], "/") - resource := strings.Split(relative, "/")[0] - domain := platformRouteDomain(resource) - for _, menu := range menus { - if menu.MenuCode == domain { - return true - } - menuPath := strings.Trim(menu.Path, "/") - if menuPath != "" && strings.Split(menuPath, "/")[0] == domain { - return true - } - } - return false -} - -func platformRouteDomain(resource string) string { - prefix := strings.Split(resource, "_")[0] - switch prefix { - case "product": - return "device" - case "gasorder": - return "delivery" - case "fin": - return "finance" - case "cms": - return "content" - case "cs": - return "customer_service" - case "platfrom", "platform": - return "platform" - default: - return prefix - } -} - -// RequirePlatformMenuAccess enforces role-menu authorization after JWT authentication. -func RequirePlatformMenuAccess() gin.HandlerFunc { - return func(ctx *gin.Context) { - if strings.Contains(ctx.Request.URL.Path, "/platform/v1/auth/") { - ctx.Next() - return - } - claims, err := middleware.ParseAuth(ctx) - if err != nil { - infra.Response.Error(ctx, err) - ctx.Abort() - return - } - if claims.Role == "root" { - ctx.Next() - return - } - menus, err := loadPlatformMenus(claims.Role) - if err != nil || !platformMenuAllowsPath(menus, ctx.Request.URL.Path) { - infra.Response.Error(ctx, errcode.ErrPermissionDenied) - ctx.Abort() - return - } - ctx.Set(platformMenusContextKey, menus) - ctx.Next() - } -} - -func requirePlatformRoot(ctx *gin.Context) bool { - claims, err := middleware.ParseAuth(ctx) - if err == nil && claims.Role == "root" { - return true - } - infra.Response.Error(ctx, errcode.ErrPermissionDenied) - return false -} diff --git a/backend/api/internal/logic/platform/product_workflow.go b/backend/api/internal/logic/platform/product_workflow.go index 1953426..c4152cf 100644 --- a/backend/api/internal/logic/platform/product_workflow.go +++ b/backend/api/internal/logic/platform/product_workflow.go @@ -354,7 +354,7 @@ func productOperator(ctx *gin.Context) (string, string) { if err != nil { return "", "" } - var account models.PlatfromAccount + var account models.PlatformAccount if err := impl.DBService.Select("display_name").Where("identity = ?", claims.Identity).First(&account).Error; err != nil { return claims.Identity, "" } diff --git a/backend/api/internal/logic/platform/resource_contract.go b/backend/api/internal/logic/platform/resource_contract.go index daaa7ef..b740c5e 100644 --- a/backend/api/internal/logic/platform/resource_contract.go +++ b/backend/api/internal/logic/platform/resource_contract.go @@ -87,7 +87,7 @@ func ExpectedResources() []ResourceContract { resourceContract("gasorder", "gasorder_track", ReadOnly, "list"), resourceContract("gasorder", "gasorder_track_point", ReadOnly, "list"), resourceContract("gasorder", "gasorder_confirm", ReadOnly, "list"), resourceContract("gasorder", "gasorder_payment", ReadOnly, "list"), resourceContract("finance", "fin_payment", Writable, "list"), resourceContract("finance", "fin_settlement", Writable, "list"), resourceContract("finance", "fin_reconciliation", Writable, "list"), resourceContract("content", "cms_content", Writable, "list"), resourceContract("customer_service", "cs_ticket", Writable, "list"), - resourceContract("platform", "platfrom_account", Writable, "list"), resourceContract("platform", "platform_role", Writable, "list"), resourceContract("platform", "platform_menu", Writable, "tree"), + resourceContract("platform", "platform_account", Writable, "list"), resourceContract("platform", "platform_role", Writable, "list"), resourceContract("platform", "platform_menu", Writable, "tree"), resourceContract("wallet", "wallet_basic", ReadOnly, "list"), resourceContract("wallet", "wallet_bank", ReadOnly, "list"), resourceContract("wallet", "wallet_payment", ReadOnly, "list"), resourceContract("wallet", "wallet_record", ReadOnly, "list"), resourceContract("wallet", "wallet_refund", ReadOnly, "list"), resourceContract("wallet", "wallet_apply_cash", ReadOnly, "list"), } } diff --git a/backend/api/internal/logic/platform/wallet_workflow.go b/backend/api/internal/logic/platform/wallet_workflow.go index 9ddf09d..befd16a 100644 --- a/backend/api/internal/logic/platform/wallet_workflow.go +++ b/backend/api/internal/logic/platform/wallet_workflow.go @@ -180,7 +180,7 @@ func UpdateWalletBasicStatus(ctx *gin.Context) { } func RechargeWalletBasic(ctx *gin.Context) { - if !requirePlatformRoot(ctx) { + if !common.RequirePlatformRoot(ctx) { return } var request struct { @@ -259,7 +259,7 @@ func RejectWalletApplyCash(ctx *gin.Context) { } func reviewWalletApplyCash(ctx *gin.Context, targetStatus string) { - if !requirePlatformRoot(ctx) { + if !common.RequirePlatformRoot(ctx) { return } var request struct { @@ -311,7 +311,7 @@ func walletOperator(ctx *gin.Context) (string, string) { if err != nil { return "", "" } - var account models.PlatfromAccount + var account models.PlatformAccount if err := impl.DBService.Select("display_name").Where("identity = ?", claims.Identity).First(&account).Error; err != nil { return claims.Identity, "" } diff --git a/backend/api/internal/models/platfrom_account.go b/backend/api/internal/models/platform_account.go similarity index 81% rename from backend/api/internal/models/platfrom_account.go rename to backend/api/internal/models/platform_account.go index 3bca661..9699fad 100644 --- a/backend/api/internal/models/platfrom_account.go +++ b/backend/api/internal/models/platform_account.go @@ -2,8 +2,8 @@ package models import "git.apinb.com/bsm-sdk/core/database" -// PlatfromAccount 对应 platfrom_account,表示平台总后台登录账号。 -type PlatfromAccount struct { +// PlatformAccount 对应 platform_account,表示平台总后台登录账号。 +type PlatformAccount struct { Entity // 公共实体字段 Username string `gorm:"column:username;type:varchar(64);uniqueIndex;not null" json:"username"` // 登录用户名 DisplayName string `gorm:"column:display_name;type:varchar(64);not null;default:''" json:"display_name"` // 用户展示名称 @@ -13,7 +13,7 @@ type PlatfromAccount struct { Phone string `gorm:"column:phone;type:varchar(32);uniqueIndex;not null;default:''" json:"phone"` // 手机号 } -func init() { database.AppendMigrate(&PlatfromAccount{}) } +func init() { database.AppendMigrate(&PlatformAccount{}) } // TableName 返回与模型、文件名一致的单数数据表名。 -func (table *PlatfromAccount) TableName() string { return "platfrom_account" } +func (table *PlatformAccount) TableName() string { return "platform_account" } diff --git a/backend/api/internal/models/platform_models_test.go b/backend/api/internal/models/platform_models_test.go new file mode 100644 index 0000000..2381eba --- /dev/null +++ b/backend/api/internal/models/platform_models_test.go @@ -0,0 +1,23 @@ +package models + +import "testing" + +func TestPlatformModelTableNames(t *testing.T) { + tests := []struct { + name string + table interface{ TableName() string } + want string + }{ + {name: "account", table: &PlatformAccount{}, want: "platform_account"}, + {name: "menu", table: &PlatformMenu{}, want: "platform_menu"}, + {name: "role", table: &PlatformRole{}, want: "platform_role"}, + {name: "role menu", table: &PlatformRoleMenu{}, want: "platform_role_menu"}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if got := test.table.TableName(); got != test.want { + t.Fatalf("TableName() = %q, want %q", got, test.want) + } + }) + } +} diff --git a/backend/api/internal/models/platform_role_menu_relation.go b/backend/api/internal/models/platform_role_menu.go similarity index 70% rename from backend/api/internal/models/platform_role_menu_relation.go rename to backend/api/internal/models/platform_role_menu.go index d8ba9eb..76ab336 100644 --- a/backend/api/internal/models/platform_role_menu_relation.go +++ b/backend/api/internal/models/platform_role_menu.go @@ -6,15 +6,15 @@ import ( "git.apinb.com/bsm-sdk/core/database" ) -// PlatformRoleMenuRelation 对应 platform_role_menu_relation,记录角色拥有的菜单权限。 -type PlatformRoleMenuRelation struct { +// PlatformRoleMenu 对应 platform_role_menu,记录角色拥有的菜单权限。 +type PlatformRoleMenu struct { ID uint64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` // 数据库自增主键 PlatformRoleID uint64 `gorm:"column:platform_role_id;not null;uniqueIndex:uk_platform_role_menu" json:"platform_role_id"` // 角色自增主键 PlatformMenuID uint64 `gorm:"column:platform_menu_id;not null;uniqueIndex:uk_platform_role_menu" json:"platform_menu_id"` // 菜单自增主键 CreatedAt time.Time `gorm:"column:created_at;type:timestamptz;not null" json:"created_at"` // 创建时间 } -func init() { database.AppendMigrate(&PlatformRoleMenuRelation{}) } +func init() { database.AppendMigrate(&PlatformRoleMenu{}) } // TableName 返回与模型、文件名一致的单数数据表名。 -func (table *PlatformRoleMenuRelation) TableName() string { return "platform_role_menu_relation" } +func (table *PlatformRoleMenu) TableName() string { return "platform_role_menu" } diff --git a/backend/api/internal/models/query.go b/backend/api/internal/models/query.go index dff973f..66dd35b 100644 --- a/backend/api/internal/models/query.go +++ b/backend/api/internal/models/query.go @@ -28,11 +28,11 @@ func GetDashboardOverview() (DashboardOverview, error) { return overview, nil } -// ListPlatfromAccount 返回平台账号分页列表,敏感字段由接口展示层脱敏。 -func ListPlatfromAccount(page, size int) ([]PlatfromAccount, int64, error) { - var list []PlatfromAccount +// ListPlatformAccount 返回平台账号分页列表,敏感字段由接口展示层脱敏。 +func ListPlatformAccount(page, size int) ([]PlatformAccount, int64, error) { + var list []PlatformAccount var total int64 - databaseQuery := impl.DBService.Model(&PlatfromAccount{}) + databaseQuery := impl.DBService.Model(&PlatformAccount{}) if err := databaseQuery.Count(&total).Error; err != nil { return nil, 0, err } diff --git a/backend/api/internal/routers/platform.go b/backend/api/internal/routers/platform.go index b1b400d..a9adc84 100644 --- a/backend/api/internal/routers/platform.go +++ b/backend/api/internal/routers/platform.go @@ -179,7 +179,13 @@ func registerUserRoute(group *gin.RouterGroup) { } func registerPlatformRoute(group *gin.RouterGroup) { - registerWritableResource(group, "/platfrom_account", platform.ListPlatfromAccount, platform.CreatePlatfromAccount, platform.GetPlatfromAccount, platform.UpdatePlatfromAccount, &models.PlatfromAccount{}) + account := group.Group("/platform_account") + account.GET("", platform.ListPlatformAccount) + account.POST("", platform.CreatePlatformAccount) + account.GET("/:identity", platform.GetPlatformAccount) + account.PUT("/:identity", platform.UpdatePlatformAccount) + account.PATCH("/:identity/status", platform.UpdatePlatformAccountStatus) + account.DELETE("/:identity", platform.ArchivePlatformAccount) role := group.Group("/platform_role") role.GET("", platform.ListPlatformRole) role.POST("", platform.CreatePlatformRole) @@ -189,7 +195,6 @@ func registerPlatformRoute(group *gin.RouterGroup) { role.DELETE("/:identity", platform.ArchivePlatformRole) role.GET("/:identity/menu", platform.ListPlatformRoleMenuIdentities) role.PUT("/:identity/menu", platform.ReplacePlatformRoleMenus) - role.PUT("/:identity/menus", platform.ReplacePlatformRoleMenus) menu := group.Group("/platform_menu") menu.GET("", platform.ListPlatformMenu) menu.POST("", platform.CreatePlatformMenu) diff --git a/backend/api/internal/routers/platform_test.go b/backend/api/internal/routers/platform_test.go index 48e4cc7..86517ed 100644 --- a/backend/api/internal/routers/platform_test.go +++ b/backend/api/internal/routers/platform_test.go @@ -85,7 +85,7 @@ func TestPlatformOrganizationAndAccountRoutesExposeResourceCRUD(t *testing.T) { "/user_account", "/user_address", "/user_service_relation", - "/platfrom_account", + "/platform_account", "/platform_role", "/platform_menu", } { @@ -95,7 +95,8 @@ func TestPlatformOrganizationAndAccountRoutesExposeResourceCRUD(t *testing.T) { } assertRouteMethods(t, routes, "/heqi/platform/v1/platform_role/:identity/menu", http.MethodGet, http.MethodPut) - assertRouteMethods(t, routes, "/heqi/platform/v1/platform_role/:identity/menus", http.MethodPut) + assertNoRouteMethods(t, routes, "/heqi/platform/v1/platform_role/:identity/menus", http.MethodGet, http.MethodPost, http.MethodPut, http.MethodPatch, http.MethodDelete) + assertNoRouteMethods(t, routes, "/heqi/platform/v1/platfrom_account", http.MethodGet, http.MethodPost, http.MethodPut, http.MethodPatch, http.MethodDelete) } func TestPlatformProductCommerceAndDeliveryRoutesFollowTheirContracts(t *testing.T) { diff --git a/frontend/platform_admin/src/api/platform.ts b/frontend/platform_admin/src/api/platform.ts index ba5ac4b..687fa9e 100644 --- a/frontend/platform_admin/src/api/platform.ts +++ b/frontend/platform_admin/src/api/platform.ts @@ -7,7 +7,7 @@ export type PlatformMenu = { identity: string; parent_identity?: string; menu_co export const platformApi = { overview: () => request>('/dashboard/overview'), - listAccount: () => request<{ total: number; list: Record[] }>('/platfrom_account'), + listAccount: () => request<{ total: number; list: Record[] }>('/platform_account'), listRole: () => resourceApi.list('/platform_role'), createRole: (data: Record) => resourceApi.create('/platform_role', data), listMenu: () => request<{ total: number; list: PlatformMenu[] }>('/platform_menu'), diff --git a/frontend/platform_admin/src/api/resources.ts b/frontend/platform_admin/src/api/resources.ts index 12f7341..1f9f89a 100644 --- a/frontend/platform_admin/src/api/resources.ts +++ b/frontend/platform_admin/src/api/resources.ts @@ -309,7 +309,7 @@ export const resources: ResourceUiDefinition[] = [ define('fin_reconciliation', '财务对账', 'writable', [f('channel', { required: true }), f('bill_date', { required: true }), f('difference_amount', { required: true })]), define('cms_content', '内容', 'writable', [f('content_type', { required: true }), f('title', { required: true }), f('body', { required: true }), f('version_no'), f('publish_status')]), define('cs_ticket', '客服工单', 'writable', [relation('user_account_identity', '/user_account', true), f('ticket_no', { required: true }), f('category', { required: true }), f('priority', { required: true })]), - define('platfrom_account', '平台账户', 'writable', [f('username', { required: true }), f('password', { required: true }), f('display_name'), f('avatar'), f('platform_role_code', { required: true }), f('phone')]), + define('platform_account', '平台账户', 'writable', [f('username', { required: true }), f('password', { required: true }), f('display_name'), f('avatar'), f('platform_role_code', { required: true }), f('phone')]), define('platform_role', '平台角色', 'writable', [f('role_code', { required: true }), f('name', { required: true }), f('data_scope', { required: true })], 'list', [ { name: '分配菜单', resource: '/platform_role/:identity/menu', method: 'PUT', fields: [f('menu_identities', { type: 'identity-list', relation: '/platform_menu' })] }, ]), diff --git a/frontend/platform_admin/src/contracts/platform-resources.json b/frontend/platform_admin/src/contracts/platform-resources.json index a5da808..ac38281 100644 --- a/frontend/platform_admin/src/contracts/platform-resources.json +++ b/frontend/platform_admin/src/contracts/platform-resources.json @@ -1 +1 @@ -{"resources":[{"domain":"gas","name":"gas_basic","path":"/gas_basic","pageKind":"list","mode":"writable"},{"domain":"gas","name":"gas_account","path":"/gas_account","pageKind":"list","mode":"writable"},{"domain":"delivery","name":"delivery_basic","path":"/delivery_basic","pageKind":"list","mode":"writable"},{"domain":"delivery","name":"delivery_account","path":"/delivery_account","pageKind":"list","mode":"writable"},{"domain":"staff","name":"staff_account","path":"/staff_account","pageKind":"list","mode":"writable"},{"domain":"staff","name":"staff_credential","path":"/staff_credential","pageKind":"list","mode":"writable"},{"domain":"user","name":"user_account","path":"/user_account","pageKind":"list","mode":"writable"},{"domain":"user","name":"user_address","path":"/user_address","pageKind":"list","mode":"writable"},{"domain":"user","name":"user_service_relation","path":"/user_service_relation","pageKind":"list","mode":"writable"},{"domain":"product","name":"product_type","path":"/product_type","pageKind":"list","mode":"editable"},{"domain":"product","name":"product_warehouse","path":"/product_warehouse","pageKind":"list","mode":"editable"},{"domain":"product","name":"product_info","path":"/product_info","pageKind":"list","mode":"editable"},{"domain":"product","name":"product_repair","path":"/product_repair","pageKind":"list","mode":"editable"},{"domain":"product","name":"product_owner","path":"/product_owner","pageKind":"list","mode":"append_only"},{"domain":"ec","name":"ec_category","path":"/ec_category","pageKind":"list","mode":"writable"},{"domain":"ec","name":"ec_product","path":"/ec_product","pageKind":"list","mode":"writable"},{"domain":"ec","name":"ec_product_attribute","path":"/ec_product_attribute","pageKind":"list","mode":"writable"},{"domain":"ec","name":"ec_product_image","path":"/ec_product_image","pageKind":"list","mode":"writable"},{"domain":"ec","name":"ec_cart","path":"/ec_cart","pageKind":"list","mode":"writable"},{"domain":"ec","name":"ec_order","path":"/ec_order","pageKind":"list","mode":"writable"},{"domain":"ec","name":"ec_order_item","path":"/ec_order_item","pageKind":"list","mode":"writable"},{"domain":"ec","name":"ec_review","path":"/ec_review","pageKind":"list","mode":"writable"},{"domain":"gasorder","name":"gasorder_contract","path":"/gasorder_contract","pageKind":"list","mode":"managed"},{"domain":"gasorder","name":"gasorder_contract_product","path":"/gasorder_contract_product","pageKind":"list","mode":"append_only"},{"domain":"gasorder","name":"gasorder_contract_revision","path":"/gasorder_contract_revision","pageKind":"list","mode":"readonly"},{"domain":"gasorder","name":"gasorder_basic","path":"/gasorder_basic","pageKind":"list","mode":"append_only"},{"domain":"gasorder","name":"gasorder_item","path":"/gasorder_item","pageKind":"list","mode":"readonly"},{"domain":"gasorder","name":"gasorder_assign","path":"/gasorder_assign","pageKind":"list","mode":"readonly"},{"domain":"gasorder","name":"gasorder_status","path":"/gasorder_status","pageKind":"list","mode":"readonly"},{"domain":"gasorder","name":"gasorder_track","path":"/gasorder_track","pageKind":"list","mode":"readonly"},{"domain":"gasorder","name":"gasorder_track_point","path":"/gasorder_track_point","pageKind":"list","mode":"readonly"},{"domain":"gasorder","name":"gasorder_confirm","path":"/gasorder_confirm","pageKind":"list","mode":"readonly"},{"domain":"gasorder","name":"gasorder_payment","path":"/gasorder_payment","pageKind":"list","mode":"readonly"},{"domain":"finance","name":"fin_payment","path":"/fin_payment","pageKind":"list","mode":"writable"},{"domain":"finance","name":"fin_settlement","path":"/fin_settlement","pageKind":"list","mode":"writable"},{"domain":"finance","name":"fin_reconciliation","path":"/fin_reconciliation","pageKind":"list","mode":"writable"},{"domain":"content","name":"cms_content","path":"/cms_content","pageKind":"list","mode":"writable"},{"domain":"customer_service","name":"cs_ticket","path":"/cs_ticket","pageKind":"list","mode":"writable"},{"domain":"platform","name":"platfrom_account","path":"/platfrom_account","pageKind":"list","mode":"writable"},{"domain":"platform","name":"platform_role","path":"/platform_role","pageKind":"list","mode":"writable"},{"domain":"platform","name":"platform_menu","path":"/platform_menu","pageKind":"tree","mode":"writable"},{"domain":"wallet","name":"wallet_basic","path":"/wallet_basic","pageKind":"list","mode":"readonly"},{"domain":"wallet","name":"wallet_bank","path":"/wallet_bank","pageKind":"list","mode":"readonly"},{"domain":"wallet","name":"wallet_payment","path":"/wallet_payment","pageKind":"list","mode":"readonly"},{"domain":"wallet","name":"wallet_record","path":"/wallet_record","pageKind":"list","mode":"readonly"},{"domain":"wallet","name":"wallet_refund","path":"/wallet_refund","pageKind":"list","mode":"readonly"},{"domain":"wallet","name":"wallet_apply_cash","path":"/wallet_apply_cash","pageKind":"list","mode":"readonly"}],"routes":[{"method":"GET","path":"/gasorder_contract"},{"method":"GET","path":"/gasorder_contract_product"},{"method":"GET","path":"/gasorder_contract_product/:identity"},{"method":"GET","path":"/gasorder_contract_revision"},{"method":"GET","path":"/gasorder_contract_revision/:identity"},{"method":"GET","path":"/gasorder_contract/:identity"},{"method":"GET","path":"/gasorder_confirm"},{"method":"GET","path":"/gasorder_confirm/:identity"},{"method":"GET","path":"/gasorder_track"},{"method":"GET","path":"/gasorder_track_point"},{"method":"GET","path":"/gasorder_track_point/:identity"},{"method":"GET","path":"/gasorder_track/:identity"},{"method":"GET","path":"/gasorder_basic"},{"method":"GET","path":"/gasorder_basic/:identity"},{"method":"GET","path":"/gasorder_item"},{"method":"GET","path":"/gasorder_item/:identity"},{"method":"GET","path":"/gasorder_assign"},{"method":"GET","path":"/gasorder_assign/:identity"},{"method":"GET","path":"/gasorder_status"},{"method":"GET","path":"/gasorder_status/:identity"},{"method":"GET","path":"/gasorder_payment"},{"method":"GET","path":"/gasorder_payment/:identity"},{"method":"GET","path":"/gas_basic"},{"method":"GET","path":"/gas_basic/:identity"},{"method":"GET","path":"/gas_account"},{"method":"GET","path":"/gas_account/:identity"},{"method":"GET","path":"/product_type"},{"method":"GET","path":"/product_type/:identity"},{"method":"GET","path":"/product_warehouse"},{"method":"GET","path":"/product_warehouse/:identity"},{"method":"GET","path":"/product_info"},{"method":"GET","path":"/product_info/:identity"},{"method":"GET","path":"/product_repair"},{"method":"GET","path":"/product_repair/:identity"},{"method":"GET","path":"/product_owner"},{"method":"GET","path":"/product_owner/:identity"},{"method":"GET","path":"/platform_role"},{"method":"GET","path":"/platform_role/:identity"},{"method":"GET","path":"/platform_role/:identity/menu"},{"method":"GET","path":"/platform_menu"},{"method":"GET","path":"/platform_menu/:identity"},{"method":"GET","path":"/platfrom_account"},{"method":"GET","path":"/platfrom_account/:identity"},{"method":"GET","path":"/ping/hello"},{"method":"GET","path":"/ec_product"},{"method":"GET","path":"/ec_product_attribute"},{"method":"GET","path":"/ec_product_attribute/:identity"},{"method":"GET","path":"/ec_product_image"},{"method":"GET","path":"/ec_product_image/:identity"},{"method":"GET","path":"/ec_product/:identity"},{"method":"GET","path":"/ec_category"},{"method":"GET","path":"/ec_category/:identity"},{"method":"GET","path":"/ec_cart"},{"method":"GET","path":"/ec_cart/:identity"},{"method":"GET","path":"/ec_order"},{"method":"GET","path":"/ec_order_item"},{"method":"GET","path":"/ec_order_item/:identity"},{"method":"GET","path":"/ec_order/:identity"},{"method":"GET","path":"/ec_review"},{"method":"GET","path":"/ec_review/:identity"},{"method":"GET","path":"/wallet_basic"},{"method":"GET","path":"/wallet_basic/owner/:owner_type/:owner_identity"},{"method":"GET","path":"/wallet_basic/:identity"},{"method":"GET","path":"/wallet_bank"},{"method":"GET","path":"/wallet_bank/:identity"},{"method":"GET","path":"/wallet_record"},{"method":"GET","path":"/wallet_record/:identity"},{"method":"GET","path":"/wallet_refund"},{"method":"GET","path":"/wallet_refund/:identity"},{"method":"GET","path":"/wallet_payment"},{"method":"GET","path":"/wallet_payment/:identity"},{"method":"GET","path":"/wallet_apply_cash"},{"method":"GET","path":"/wallet_apply_cash/:identity"},{"method":"GET","path":"/user_account"},{"method":"GET","path":"/user_account/:identity"},{"method":"GET","path":"/user_address"},{"method":"GET","path":"/user_address/:identity"},{"method":"GET","path":"/user_service_relation"},{"method":"GET","path":"/user_service_relation/:identity"},{"method":"GET","path":"/fin_payment"},{"method":"GET","path":"/fin_payment/:identity"},{"method":"GET","path":"/fin_settlement"},{"method":"GET","path":"/fin_settlement/:identity"},{"method":"GET","path":"/fin_reconciliation"},{"method":"GET","path":"/fin_reconciliation/:identity"},{"method":"GET","path":"/delivery_basic"},{"method":"GET","path":"/delivery_basic/:identity"},{"method":"GET","path":"/delivery_account"},{"method":"GET","path":"/delivery_account/:identity"},{"method":"GET","path":"/dashboard/overview"},{"method":"GET","path":"/staff_account"},{"method":"GET","path":"/staff_account/:identity"},{"method":"GET","path":"/staff_credential"},{"method":"GET","path":"/staff_credential/:identity"},{"method":"GET","path":"/cms_content"},{"method":"GET","path":"/cms_content/:identity"},{"method":"GET","path":"/cs_ticket"},{"method":"GET","path":"/cs_ticket/:identity"},{"method":"GET","path":"/auth/profile"},{"method":"POST","path":"/gasorder_basic"},{"method":"POST","path":"/gasorder_basic/:identity/ready"},{"method":"POST","path":"/gasorder_basic/:identity/recover"},{"method":"POST","path":"/gasorder_basic/:identity/assign"},{"method":"POST","path":"/gasorder_basic/:identity/filling"},{"method":"POST","path":"/gasorder_basic/:identity/exception"},{"method":"POST","path":"/gasorder_basic/:identity/cancel"},{"method":"POST","path":"/gasorder_contract"},{"method":"POST","path":"/gasorder_contract/:identity/activate"},{"method":"POST","path":"/gasorder_contract/:identity/renew"},{"method":"POST","path":"/gasorder_contract/:identity/terminate"},{"method":"POST","path":"/gasorder_contract_product"},{"method":"POST","path":"/gasorder_contract_product/:identity/unbind"},{"method":"POST","path":"/gas_basic"},{"method":"POST","path":"/gas_account"},{"method":"POST","path":"/ec_product"},{"method":"POST","path":"/ec_product_attribute"},{"method":"POST","path":"/ec_product_image"},{"method":"POST","path":"/ec_category"},{"method":"POST","path":"/ec_cart"},{"method":"POST","path":"/ec_order"},{"method":"POST","path":"/ec_order_item"},{"method":"POST","path":"/ec_review"},{"method":"POST","path":"/product_type"},{"method":"POST","path":"/product_warehouse"},{"method":"POST","path":"/product_info"},{"method":"POST","path":"/product_repair"},{"method":"POST","path":"/product_owner"},{"method":"POST","path":"/platform_role"},{"method":"POST","path":"/platform_menu"},{"method":"POST","path":"/platfrom_account"},{"method":"POST","path":"/user_account"},{"method":"POST","path":"/user_address"},{"method":"POST","path":"/user_service_relation"},{"method":"POST","path":"/wallet_apply_cash/:identity/approve"},{"method":"POST","path":"/wallet_apply_cash/:identity/reject"},{"method":"POST","path":"/wallet_basic/:identity/recharge"},{"method":"POST","path":"/fin_payment"},{"method":"POST","path":"/fin_settlement"},{"method":"POST","path":"/fin_reconciliation"},{"method":"POST","path":"/delivery_basic"},{"method":"POST","path":"/delivery_account"},{"method":"POST","path":"/staff_account"},{"method":"POST","path":"/staff_credential"},{"method":"POST","path":"/cms_content"},{"method":"POST","path":"/cs_ticket"},{"method":"POST","path":"/auth/login"},{"method":"PUT","path":"/platform_role/:identity"},{"method":"PUT","path":"/platform_role/:identity/menu"},{"method":"PUT","path":"/platform_role/:identity/menus"},{"method":"PUT","path":"/platform_menu/:identity"},{"method":"PUT","path":"/platfrom_account/:identity"},{"method":"PUT","path":"/product_type/:identity"},{"method":"PUT","path":"/product_warehouse/:identity"},{"method":"PUT","path":"/product_info/:identity"},{"method":"PUT","path":"/product_repair/:identity"},{"method":"PUT","path":"/ec_product_attribute/:identity"},{"method":"PUT","path":"/ec_product_image/:identity"},{"method":"PUT","path":"/ec_product/:identity"},{"method":"PUT","path":"/ec_category/:identity"},{"method":"PUT","path":"/ec_cart/:identity"},{"method":"PUT","path":"/ec_order/:identity"},{"method":"PUT","path":"/ec_order_item/:identity"},{"method":"PUT","path":"/ec_review/:identity"},{"method":"PUT","path":"/gas_basic/:identity"},{"method":"PUT","path":"/gas_account/:identity"},{"method":"PUT","path":"/gasorder_contract/:identity"},{"method":"PUT","path":"/user_account/:identity"},{"method":"PUT","path":"/user_address/:identity"},{"method":"PUT","path":"/user_service_relation/:identity"},{"method":"PUT","path":"/fin_payment/:identity"},{"method":"PUT","path":"/fin_settlement/:identity"},{"method":"PUT","path":"/fin_reconciliation/:identity"},{"method":"PUT","path":"/delivery_basic/:identity"},{"method":"PUT","path":"/delivery_account/:identity"},{"method":"PUT","path":"/staff_account/:identity"},{"method":"PUT","path":"/staff_credential/:identity"},{"method":"PUT","path":"/cms_content/:identity"},{"method":"PUT","path":"/cs_ticket/:identity"},{"method":"PUT","path":"/auth/password"},{"method":"PATCH","path":"/ec_product_attribute/:identity/status"},{"method":"PATCH","path":"/ec_product_image/:identity/status"},{"method":"PATCH","path":"/ec_product/:identity/status"},{"method":"PATCH","path":"/ec_category/:identity/status"},{"method":"PATCH","path":"/ec_cart/:identity/status"},{"method":"PATCH","path":"/ec_order/:identity/status"},{"method":"PATCH","path":"/ec_order_item/:identity/status"},{"method":"PATCH","path":"/ec_review/:identity/status"},{"method":"PATCH","path":"/product_type/:identity/status"},{"method":"PATCH","path":"/product_warehouse/:identity/status"},{"method":"PATCH","path":"/product_info/:identity/status"},{"method":"PATCH","path":"/product_repair/:identity/status"},{"method":"PATCH","path":"/platform_role/:identity/status"},{"method":"PATCH","path":"/platform_menu/:identity/status"},{"method":"PATCH","path":"/platfrom_account/:identity/status"},{"method":"PATCH","path":"/user_account/:identity/status"},{"method":"PATCH","path":"/user_address/:identity/status"},{"method":"PATCH","path":"/user_service_relation/:identity/status"},{"method":"PATCH","path":"/fin_payment/:identity/status"},{"method":"PATCH","path":"/fin_settlement/:identity/status"},{"method":"PATCH","path":"/fin_reconciliation/:identity/status"},{"method":"PATCH","path":"/gas_basic/:identity/status"},{"method":"PATCH","path":"/gas_account/:identity/status"},{"method":"PATCH","path":"/delivery_basic/:identity/status"},{"method":"PATCH","path":"/delivery_account/:identity/status"},{"method":"PATCH","path":"/staff_account/:identity/status"},{"method":"PATCH","path":"/staff_credential/:identity/status"},{"method":"PATCH","path":"/cms_content/:identity/status"},{"method":"PATCH","path":"/cs_ticket/:identity/status"},{"method":"PATCH","path":"/wallet_basic/:identity/status"},{"method":"DELETE","path":"/ec_product_attribute/:identity"},{"method":"DELETE","path":"/ec_product_image/:identity"},{"method":"DELETE","path":"/ec_product/:identity"},{"method":"DELETE","path":"/ec_category/:identity"},{"method":"DELETE","path":"/ec_cart/:identity"},{"method":"DELETE","path":"/ec_order/:identity"},{"method":"DELETE","path":"/ec_order_item/:identity"},{"method":"DELETE","path":"/ec_review/:identity"},{"method":"DELETE","path":"/user_account/:identity"},{"method":"DELETE","path":"/user_address/:identity"},{"method":"DELETE","path":"/user_service_relation/:identity"},{"method":"DELETE","path":"/fin_payment/:identity"},{"method":"DELETE","path":"/fin_settlement/:identity"},{"method":"DELETE","path":"/fin_reconciliation/:identity"},{"method":"DELETE","path":"/platform_role/:identity"},{"method":"DELETE","path":"/platform_menu/:identity"},{"method":"DELETE","path":"/platfrom_account/:identity"},{"method":"DELETE","path":"/gas_basic/:identity"},{"method":"DELETE","path":"/gas_account/:identity"},{"method":"DELETE","path":"/delivery_basic/:identity"},{"method":"DELETE","path":"/delivery_account/:identity"},{"method":"DELETE","path":"/staff_account/:identity"},{"method":"DELETE","path":"/staff_credential/:identity"},{"method":"DELETE","path":"/cms_content/:identity"},{"method":"DELETE","path":"/cs_ticket/:identity"}]} +{"resources":[{"domain":"gas","name":"gas_basic","path":"/gas_basic","pageKind":"list","mode":"writable"},{"domain":"gas","name":"gas_account","path":"/gas_account","pageKind":"list","mode":"writable"},{"domain":"delivery","name":"delivery_basic","path":"/delivery_basic","pageKind":"list","mode":"writable"},{"domain":"delivery","name":"delivery_account","path":"/delivery_account","pageKind":"list","mode":"writable"},{"domain":"staff","name":"staff_account","path":"/staff_account","pageKind":"list","mode":"writable"},{"domain":"staff","name":"staff_credential","path":"/staff_credential","pageKind":"list","mode":"writable"},{"domain":"user","name":"user_account","path":"/user_account","pageKind":"list","mode":"writable"},{"domain":"user","name":"user_address","path":"/user_address","pageKind":"list","mode":"writable"},{"domain":"user","name":"user_service_relation","path":"/user_service_relation","pageKind":"list","mode":"writable"},{"domain":"product","name":"product_type","path":"/product_type","pageKind":"list","mode":"editable"},{"domain":"product","name":"product_warehouse","path":"/product_warehouse","pageKind":"list","mode":"editable"},{"domain":"product","name":"product_info","path":"/product_info","pageKind":"list","mode":"editable"},{"domain":"product","name":"product_repair","path":"/product_repair","pageKind":"list","mode":"editable"},{"domain":"product","name":"product_owner","path":"/product_owner","pageKind":"list","mode":"append_only"},{"domain":"ec","name":"ec_category","path":"/ec_category","pageKind":"list","mode":"writable"},{"domain":"ec","name":"ec_product","path":"/ec_product","pageKind":"list","mode":"writable"},{"domain":"ec","name":"ec_product_attribute","path":"/ec_product_attribute","pageKind":"list","mode":"writable"},{"domain":"ec","name":"ec_product_image","path":"/ec_product_image","pageKind":"list","mode":"writable"},{"domain":"ec","name":"ec_cart","path":"/ec_cart","pageKind":"list","mode":"writable"},{"domain":"ec","name":"ec_order","path":"/ec_order","pageKind":"list","mode":"writable"},{"domain":"ec","name":"ec_order_item","path":"/ec_order_item","pageKind":"list","mode":"writable"},{"domain":"ec","name":"ec_review","path":"/ec_review","pageKind":"list","mode":"writable"},{"domain":"gasorder","name":"gasorder_contract","path":"/gasorder_contract","pageKind":"list","mode":"managed"},{"domain":"gasorder","name":"gasorder_contract_product","path":"/gasorder_contract_product","pageKind":"list","mode":"append_only"},{"domain":"gasorder","name":"gasorder_contract_revision","path":"/gasorder_contract_revision","pageKind":"list","mode":"readonly"},{"domain":"gasorder","name":"gasorder_basic","path":"/gasorder_basic","pageKind":"list","mode":"append_only"},{"domain":"gasorder","name":"gasorder_item","path":"/gasorder_item","pageKind":"list","mode":"readonly"},{"domain":"gasorder","name":"gasorder_assign","path":"/gasorder_assign","pageKind":"list","mode":"readonly"},{"domain":"gasorder","name":"gasorder_status","path":"/gasorder_status","pageKind":"list","mode":"readonly"},{"domain":"gasorder","name":"gasorder_track","path":"/gasorder_track","pageKind":"list","mode":"readonly"},{"domain":"gasorder","name":"gasorder_track_point","path":"/gasorder_track_point","pageKind":"list","mode":"readonly"},{"domain":"gasorder","name":"gasorder_confirm","path":"/gasorder_confirm","pageKind":"list","mode":"readonly"},{"domain":"gasorder","name":"gasorder_payment","path":"/gasorder_payment","pageKind":"list","mode":"readonly"},{"domain":"finance","name":"fin_payment","path":"/fin_payment","pageKind":"list","mode":"writable"},{"domain":"finance","name":"fin_settlement","path":"/fin_settlement","pageKind":"list","mode":"writable"},{"domain":"finance","name":"fin_reconciliation","path":"/fin_reconciliation","pageKind":"list","mode":"writable"},{"domain":"content","name":"cms_content","path":"/cms_content","pageKind":"list","mode":"writable"},{"domain":"customer_service","name":"cs_ticket","path":"/cs_ticket","pageKind":"list","mode":"writable"},{"domain":"platform","name":"platform_account","path":"/platform_account","pageKind":"list","mode":"writable"},{"domain":"platform","name":"platform_role","path":"/platform_role","pageKind":"list","mode":"writable"},{"domain":"platform","name":"platform_menu","path":"/platform_menu","pageKind":"tree","mode":"writable"},{"domain":"wallet","name":"wallet_basic","path":"/wallet_basic","pageKind":"list","mode":"readonly"},{"domain":"wallet","name":"wallet_bank","path":"/wallet_bank","pageKind":"list","mode":"readonly"},{"domain":"wallet","name":"wallet_payment","path":"/wallet_payment","pageKind":"list","mode":"readonly"},{"domain":"wallet","name":"wallet_record","path":"/wallet_record","pageKind":"list","mode":"readonly"},{"domain":"wallet","name":"wallet_refund","path":"/wallet_refund","pageKind":"list","mode":"readonly"},{"domain":"wallet","name":"wallet_apply_cash","path":"/wallet_apply_cash","pageKind":"list","mode":"readonly"}],"routes":[{"method":"GET","path":"/gasorder_contract"},{"method":"GET","path":"/gasorder_contract_product"},{"method":"GET","path":"/gasorder_contract_product/:identity"},{"method":"GET","path":"/gasorder_contract_revision"},{"method":"GET","path":"/gasorder_contract_revision/:identity"},{"method":"GET","path":"/gasorder_contract/:identity"},{"method":"GET","path":"/gasorder_confirm"},{"method":"GET","path":"/gasorder_confirm/:identity"},{"method":"GET","path":"/gasorder_track"},{"method":"GET","path":"/gasorder_track_point"},{"method":"GET","path":"/gasorder_track_point/:identity"},{"method":"GET","path":"/gasorder_track/:identity"},{"method":"GET","path":"/gasorder_basic"},{"method":"GET","path":"/gasorder_basic/:identity"},{"method":"GET","path":"/gasorder_item"},{"method":"GET","path":"/gasorder_item/:identity"},{"method":"GET","path":"/gasorder_assign"},{"method":"GET","path":"/gasorder_assign/:identity"},{"method":"GET","path":"/gasorder_status"},{"method":"GET","path":"/gasorder_status/:identity"},{"method":"GET","path":"/gasorder_payment"},{"method":"GET","path":"/gasorder_payment/:identity"},{"method":"GET","path":"/gas_basic"},{"method":"GET","path":"/gas_basic/:identity"},{"method":"GET","path":"/gas_account"},{"method":"GET","path":"/gas_account/:identity"},{"method":"GET","path":"/product_type"},{"method":"GET","path":"/product_type/:identity"},{"method":"GET","path":"/product_warehouse"},{"method":"GET","path":"/product_warehouse/:identity"},{"method":"GET","path":"/product_info"},{"method":"GET","path":"/product_info/:identity"},{"method":"GET","path":"/product_repair"},{"method":"GET","path":"/product_repair/:identity"},{"method":"GET","path":"/product_owner"},{"method":"GET","path":"/product_owner/:identity"},{"method":"GET","path":"/platform_role"},{"method":"GET","path":"/platform_role/:identity"},{"method":"GET","path":"/platform_role/:identity/menu"},{"method":"GET","path":"/platform_account"},{"method":"GET","path":"/platform_account/:identity"},{"method":"GET","path":"/platform_menu"},{"method":"GET","path":"/platform_menu/:identity"},{"method":"GET","path":"/ping/hello"},{"method":"GET","path":"/ec_product"},{"method":"GET","path":"/ec_product_attribute"},{"method":"GET","path":"/ec_product_attribute/:identity"},{"method":"GET","path":"/ec_product_image"},{"method":"GET","path":"/ec_product_image/:identity"},{"method":"GET","path":"/ec_product/:identity"},{"method":"GET","path":"/ec_category"},{"method":"GET","path":"/ec_category/:identity"},{"method":"GET","path":"/ec_cart"},{"method":"GET","path":"/ec_cart/:identity"},{"method":"GET","path":"/ec_order"},{"method":"GET","path":"/ec_order_item"},{"method":"GET","path":"/ec_order_item/:identity"},{"method":"GET","path":"/ec_order/:identity"},{"method":"GET","path":"/ec_review"},{"method":"GET","path":"/ec_review/:identity"},{"method":"GET","path":"/wallet_basic"},{"method":"GET","path":"/wallet_basic/owner/:owner_type/:owner_identity"},{"method":"GET","path":"/wallet_basic/:identity"},{"method":"GET","path":"/wallet_bank"},{"method":"GET","path":"/wallet_bank/:identity"},{"method":"GET","path":"/wallet_record"},{"method":"GET","path":"/wallet_record/:identity"},{"method":"GET","path":"/wallet_refund"},{"method":"GET","path":"/wallet_refund/:identity"},{"method":"GET","path":"/wallet_payment"},{"method":"GET","path":"/wallet_payment/:identity"},{"method":"GET","path":"/wallet_apply_cash"},{"method":"GET","path":"/wallet_apply_cash/:identity"},{"method":"GET","path":"/user_account"},{"method":"GET","path":"/user_account/:identity"},{"method":"GET","path":"/user_address"},{"method":"GET","path":"/user_address/:identity"},{"method":"GET","path":"/user_service_relation"},{"method":"GET","path":"/user_service_relation/:identity"},{"method":"GET","path":"/fin_payment"},{"method":"GET","path":"/fin_payment/:identity"},{"method":"GET","path":"/fin_settlement"},{"method":"GET","path":"/fin_settlement/:identity"},{"method":"GET","path":"/fin_reconciliation"},{"method":"GET","path":"/fin_reconciliation/:identity"},{"method":"GET","path":"/delivery_basic"},{"method":"GET","path":"/delivery_basic/:identity"},{"method":"GET","path":"/delivery_account"},{"method":"GET","path":"/delivery_account/:identity"},{"method":"GET","path":"/dashboard/overview"},{"method":"GET","path":"/staff_account"},{"method":"GET","path":"/staff_account/:identity"},{"method":"GET","path":"/staff_credential"},{"method":"GET","path":"/staff_credential/:identity"},{"method":"GET","path":"/cms_content"},{"method":"GET","path":"/cms_content/:identity"},{"method":"GET","path":"/cs_ticket"},{"method":"GET","path":"/cs_ticket/:identity"},{"method":"GET","path":"/auth/profile"},{"method":"POST","path":"/gasorder_basic"},{"method":"POST","path":"/gasorder_basic/:identity/ready"},{"method":"POST","path":"/gasorder_basic/:identity/recover"},{"method":"POST","path":"/gasorder_basic/:identity/assign"},{"method":"POST","path":"/gasorder_basic/:identity/filling"},{"method":"POST","path":"/gasorder_basic/:identity/exception"},{"method":"POST","path":"/gasorder_basic/:identity/cancel"},{"method":"POST","path":"/gasorder_contract"},{"method":"POST","path":"/gasorder_contract/:identity/activate"},{"method":"POST","path":"/gasorder_contract/:identity/renew"},{"method":"POST","path":"/gasorder_contract/:identity/terminate"},{"method":"POST","path":"/gasorder_contract_product"},{"method":"POST","path":"/gasorder_contract_product/:identity/unbind"},{"method":"POST","path":"/gas_basic"},{"method":"POST","path":"/gas_account"},{"method":"POST","path":"/ec_product"},{"method":"POST","path":"/ec_product_attribute"},{"method":"POST","path":"/ec_product_image"},{"method":"POST","path":"/ec_category"},{"method":"POST","path":"/ec_cart"},{"method":"POST","path":"/ec_order"},{"method":"POST","path":"/ec_order_item"},{"method":"POST","path":"/ec_review"},{"method":"POST","path":"/product_type"},{"method":"POST","path":"/product_warehouse"},{"method":"POST","path":"/product_info"},{"method":"POST","path":"/product_repair"},{"method":"POST","path":"/product_owner"},{"method":"POST","path":"/platform_account"},{"method":"POST","path":"/platform_role"},{"method":"POST","path":"/platform_menu"},{"method":"POST","path":"/user_account"},{"method":"POST","path":"/user_address"},{"method":"POST","path":"/user_service_relation"},{"method":"POST","path":"/wallet_apply_cash/:identity/approve"},{"method":"POST","path":"/wallet_apply_cash/:identity/reject"},{"method":"POST","path":"/wallet_basic/:identity/recharge"},{"method":"POST","path":"/fin_payment"},{"method":"POST","path":"/fin_settlement"},{"method":"POST","path":"/fin_reconciliation"},{"method":"POST","path":"/delivery_basic"},{"method":"POST","path":"/delivery_account"},{"method":"POST","path":"/staff_account"},{"method":"POST","path":"/staff_credential"},{"method":"POST","path":"/cms_content"},{"method":"POST","path":"/cs_ticket"},{"method":"POST","path":"/auth/login"},{"method":"PUT","path":"/ec_product_attribute/:identity"},{"method":"PUT","path":"/ec_product_image/:identity"},{"method":"PUT","path":"/ec_product/:identity"},{"method":"PUT","path":"/ec_category/:identity"},{"method":"PUT","path":"/ec_cart/:identity"},{"method":"PUT","path":"/ec_order/:identity"},{"method":"PUT","path":"/ec_order_item/:identity"},{"method":"PUT","path":"/ec_review/:identity"},{"method":"PUT","path":"/product_type/:identity"},{"method":"PUT","path":"/product_warehouse/:identity"},{"method":"PUT","path":"/product_info/:identity"},{"method":"PUT","path":"/product_repair/:identity"},{"method":"PUT","path":"/platform_role/:identity"},{"method":"PUT","path":"/platform_role/:identity/menu"},{"method":"PUT","path":"/platform_account/:identity"},{"method":"PUT","path":"/platform_menu/:identity"},{"method":"PUT","path":"/gas_basic/:identity"},{"method":"PUT","path":"/gas_account/:identity"},{"method":"PUT","path":"/gasorder_contract/:identity"},{"method":"PUT","path":"/user_account/:identity"},{"method":"PUT","path":"/user_address/:identity"},{"method":"PUT","path":"/user_service_relation/:identity"},{"method":"PUT","path":"/fin_payment/:identity"},{"method":"PUT","path":"/fin_settlement/:identity"},{"method":"PUT","path":"/fin_reconciliation/:identity"},{"method":"PUT","path":"/delivery_basic/:identity"},{"method":"PUT","path":"/delivery_account/:identity"},{"method":"PUT","path":"/staff_account/:identity"},{"method":"PUT","path":"/staff_credential/:identity"},{"method":"PUT","path":"/cms_content/:identity"},{"method":"PUT","path":"/cs_ticket/:identity"},{"method":"PUT","path":"/auth/password"},{"method":"PATCH","path":"/ec_product_attribute/:identity/status"},{"method":"PATCH","path":"/ec_product_image/:identity/status"},{"method":"PATCH","path":"/ec_product/:identity/status"},{"method":"PATCH","path":"/ec_category/:identity/status"},{"method":"PATCH","path":"/ec_cart/:identity/status"},{"method":"PATCH","path":"/ec_order/:identity/status"},{"method":"PATCH","path":"/ec_order_item/:identity/status"},{"method":"PATCH","path":"/ec_review/:identity/status"},{"method":"PATCH","path":"/product_type/:identity/status"},{"method":"PATCH","path":"/product_warehouse/:identity/status"},{"method":"PATCH","path":"/product_info/:identity/status"},{"method":"PATCH","path":"/product_repair/:identity/status"},{"method":"PATCH","path":"/platform_account/:identity/status"},{"method":"PATCH","path":"/platform_role/:identity/status"},{"method":"PATCH","path":"/platform_menu/:identity/status"},{"method":"PATCH","path":"/user_account/:identity/status"},{"method":"PATCH","path":"/user_address/:identity/status"},{"method":"PATCH","path":"/user_service_relation/:identity/status"},{"method":"PATCH","path":"/fin_payment/:identity/status"},{"method":"PATCH","path":"/fin_settlement/:identity/status"},{"method":"PATCH","path":"/fin_reconciliation/:identity/status"},{"method":"PATCH","path":"/gas_basic/:identity/status"},{"method":"PATCH","path":"/gas_account/:identity/status"},{"method":"PATCH","path":"/delivery_basic/:identity/status"},{"method":"PATCH","path":"/delivery_account/:identity/status"},{"method":"PATCH","path":"/staff_account/:identity/status"},{"method":"PATCH","path":"/staff_credential/:identity/status"},{"method":"PATCH","path":"/cms_content/:identity/status"},{"method":"PATCH","path":"/cs_ticket/:identity/status"},{"method":"PATCH","path":"/wallet_basic/:identity/status"},{"method":"DELETE","path":"/ec_product_attribute/:identity"},{"method":"DELETE","path":"/ec_product_image/:identity"},{"method":"DELETE","path":"/ec_product/:identity"},{"method":"DELETE","path":"/ec_category/:identity"},{"method":"DELETE","path":"/ec_cart/:identity"},{"method":"DELETE","path":"/ec_order/:identity"},{"method":"DELETE","path":"/ec_order_item/:identity"},{"method":"DELETE","path":"/ec_review/:identity"},{"method":"DELETE","path":"/user_account/:identity"},{"method":"DELETE","path":"/user_address/:identity"},{"method":"DELETE","path":"/user_service_relation/:identity"},{"method":"DELETE","path":"/fin_payment/:identity"},{"method":"DELETE","path":"/fin_settlement/:identity"},{"method":"DELETE","path":"/fin_reconciliation/:identity"},{"method":"DELETE","path":"/platform_account/:identity"},{"method":"DELETE","path":"/platform_role/:identity"},{"method":"DELETE","path":"/platform_menu/:identity"},{"method":"DELETE","path":"/gas_basic/:identity"},{"method":"DELETE","path":"/gas_account/:identity"},{"method":"DELETE","path":"/delivery_basic/:identity"},{"method":"DELETE","path":"/delivery_account/:identity"},{"method":"DELETE","path":"/staff_account/:identity"},{"method":"DELETE","path":"/staff_credential/:identity"},{"method":"DELETE","path":"/cms_content/:identity"},{"method":"DELETE","path":"/cs_ticket/:identity"}]} diff --git a/frontend/platform_admin/src/router/routes/modules/platform.ts b/frontend/platform_admin/src/router/routes/modules/platform.ts index f96b8d6..4afec14 100644 --- a/frontend/platform_admin/src/router/routes/modules/platform.ts +++ b/frontend/platform_admin/src/router/routes/modules/platform.ts @@ -109,7 +109,7 @@ const routes: AppRouteRecordRaw[] = [ child('customer_service', 'tickets', 'tickets', '客服工单', '/cs_ticket'), ]), group('platform', 'platform', '平台管理', 'icon-settings', 120, [ - child('platform', 'accounts', 'accounts', '平台账户', '/platfrom_account'), + child('platform', 'accounts', 'accounts', '平台账户', '/platform_account'), child('platform', 'roles', 'roles', '平台角色', '/platform_role'), child('platform', 'menus', 'menus', '平台菜单', '/platform_menu'), ]),