Files
platforms/backend/api/internal/logic/platform/resource.go
2026-07-28 08:45:42 +08:00

113 lines
4.9 KiB
Go

package platform
import (
"net/http"
"github.com/gin-gonic/gin"
)
// ResourceMode describes the operations a platform-admin resource supports.
type ResourceMode string
const (
Writable ResourceMode = "writable"
ReadOnly ResourceMode = "readonly"
AppendOnly ResourceMode = "append_only"
Editable ResourceMode = "editable"
)
// ResourceContract is the expected cross-layer representation of one resource.
type ResourceContract struct {
Domain string
Name string
Path string
PageKind string
Mode ResourceMode
}
// ResourceDefinition describes a route resource and the fields it may change.
type ResourceDefinition struct {
Domain string
Name string
Model func() any
Mode ResourceMode
CreateFields []string
UpdateFields []string
}
// Allows reports whether a resource mode supports an HTTP method.
func (d ResourceDefinition) Allows(method string) bool {
switch d.Mode {
case ReadOnly:
return method == http.MethodGet
case AppendOnly:
return method == http.MethodGet || method == http.MethodPost
case Editable:
return method == http.MethodGet || method == http.MethodPost || method == http.MethodPut || method == http.MethodPatch
case Writable:
return method == http.MethodGet || method == http.MethodPost || method == http.MethodPut || method == http.MethodPatch || method == http.MethodDelete
default:
return false
}
}
func archiveValues() gin.H {
return gin.H{"status": "archived"}
}
func filterFields(values map[string]any, allowedFields []string) gin.H {
allowed := make(map[string]struct{}, len(allowedFields))
for _, field := range allowedFields {
allowed[field] = struct{}{}
}
filtered := make(gin.H, len(allowed))
for field, value := range values {
if _, ok := allowed[field]; ok {
filtered[field] = value
}
}
return filtered
}
// ExpectedResources returns the complete platform-admin resource catalogue.
func ExpectedResources() []ResourceContract {
return []ResourceContract{
resourceContract("gas", "gas_basic", Writable, "list"), resourceContract("gas", "gas_account", Writable, "list"),
resourceContract("delivery", "delivery_basic", Writable, "list"), resourceContract("delivery", "delivery_account", Writable, "list"),
resourceContract("staff", "staff_account", Writable, "list"), resourceContract("staff", "staff_credential", Writable, "list"),
resourceContract("user", "user_account", Writable, "list"), resourceContract("user", "user_address", Writable, "list"), resourceContract("user", "user_service_relation", Writable, "list"),
resourceContract("product", "product_type", Editable, "list"), resourceContract("product", "product_warehouse", Editable, "list"), resourceContract("product", "product_info", Editable, "list"), resourceContract("product", "product_repair", Editable, "list"), resourceContract("product", "product_owner", AppendOnly, "list"),
resourceContract("ec", "ec_category", Writable, "list"), resourceContract("ec", "ec_product", Writable, "list"), resourceContract("ec", "ec_product_attribute", Writable, "list"), resourceContract("ec", "ec_product_image", Writable, "list"), resourceContract("ec", "ec_cart", Writable, "list"), resourceContract("ec", "ec_order", Writable, "list"), resourceContract("ec", "ec_order_item", Writable, "list"), resourceContract("ec", "ec_review", Writable, "list"),
resourceContract("delivery", "delivery_task", Writable, "list"), resourceContract("delivery", "delivery_track", Writable, "list"), resourceContract("delivery", "delivery_track_point", 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("wallet", "wallet", ReadOnly, "list"), resourceContract("wallet", "wallet_ledger", ReadOnly, "list"), resourceContract("wallet", "wallet_recharge", ReadOnly, "list"), resourceContract("wallet", "wallet_withdrawal", ReadOnly, "list"),
}
}
func resourceContract(domain, name string, mode ResourceMode, pageKind string) ResourceContract {
return ResourceContract{Domain: domain, Name: name, Path: resourcePath(domain, name), Mode: mode, PageKind: pageKind}
}
func resourcePath(domain, name string) string {
if domain == "product" {
return "/" + name
}
switch name {
case "staff_account":
return "/staff/account"
case "staff_credential":
return "/staff/credential"
case "user_account":
return "/user/account"
case "user_address":
return "/user/address"
case "user_service_relation":
return "/user/service_relation"
default:
return "/" + domain + "/" + name
}
}