Backend (Go)
- Include custom endpoints in each model’s SupportedEndpointTypes by parsing Model.Endpoints (JSON) and appending keys alongside native endpoint types.
- Build a global supportedEndpointMap map[string]EndpointInfo{path, method} by:
- Seeding with native defaults.
- Overriding/adding from models.endpoints (accepts string path → default POST, or {path, method}).
- Expose supported_endpoint at the top level of /api/pricing (vendors-like), removing per-model duplication.
- Fix default path for EndpointTypeOpenAIResponse to /v1/responses.
- Keep concurrency/caching for pricing retrieval intact.
Frontend (React)
- Fetch supported_endpoint in useModelPricingData and propagate to PricingPage → ModelDetailSideSheet → ModelEndpoints.
- ModelEndpoints
- Resolve path+method via endpointMap; replace {model} with actual model name.
- Fix mobile visibility; always show path and HTTP method.
- JSONEditor
- Wrap with Form.Slot to inherit form layout; simplify visual styles.
- Use Tabs for “Visual” / “Manual” modes.
- Unify editors: key-value editor now supports nested JSON:
- “+” to convert a primitive into an object and add nested fields.
- Add “Convert to value” for two‑way toggle back from object.
- Stable key rename without reordering rows; new rows append at bottom.
- Use Row/Col grid for clean alignment; region editor uses Form.Slot + grid.
- Editing flows
- EditModelModal / EditPrefillGroupModal use JSONEditor (editorType='object') for endpoint mappings.
- PrefillGroupManagement renders endpoint group items by JSON keys.
Data expectations / compatibility
- models.endpoints should be a JSON object mapping endpoint type → string path or {path, method}. Strings default to POST.
- No schema changes; existing TEXT field continues to store JSON.
QA
- /api/pricing now returns custom endpoint types and global supported_endpoint.
- UI shows both native and custom endpoints; paths/methods render on mobile; nested editing works and preserves order.
74 lines
1.6 KiB
Go
74 lines
1.6 KiB
Go
package controller
|
|
|
|
import (
|
|
"one-api/model"
|
|
"one-api/setting"
|
|
"one-api/setting/ratio_setting"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
func GetPricing(c *gin.Context) {
|
|
pricing := model.GetPricing()
|
|
userId, exists := c.Get("id")
|
|
usableGroup := map[string]string{}
|
|
groupRatio := map[string]float64{}
|
|
for s, f := range ratio_setting.GetGroupRatioCopy() {
|
|
groupRatio[s] = f
|
|
}
|
|
var group string
|
|
if exists {
|
|
user, err := model.GetUserCache(userId.(int))
|
|
if err == nil {
|
|
group = user.Group
|
|
for g := range groupRatio {
|
|
ratio, ok := ratio_setting.GetGroupGroupRatio(group, g)
|
|
if ok {
|
|
groupRatio[g] = ratio
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
usableGroup = setting.GetUserUsableGroups(group)
|
|
// check groupRatio contains usableGroup
|
|
for group := range ratio_setting.GetGroupRatioCopy() {
|
|
if _, ok := usableGroup[group]; !ok {
|
|
delete(groupRatio, group)
|
|
}
|
|
}
|
|
|
|
c.JSON(200, gin.H{
|
|
"success": true,
|
|
"data": pricing,
|
|
"vendors": model.GetVendors(),
|
|
"group_ratio": groupRatio,
|
|
"usable_group": usableGroup,
|
|
"supported_endpoint": model.GetSupportedEndpointMap(),
|
|
})
|
|
}
|
|
|
|
func ResetModelRatio(c *gin.Context) {
|
|
defaultStr := ratio_setting.DefaultModelRatio2JSONString()
|
|
err := model.UpdateOption("ModelRatio", defaultStr)
|
|
if err != nil {
|
|
c.JSON(200, gin.H{
|
|
"success": false,
|
|
"message": err.Error(),
|
|
})
|
|
return
|
|
}
|
|
err = ratio_setting.UpdateModelRatioByJSONString(defaultStr)
|
|
if err != nil {
|
|
c.JSON(200, gin.H{
|
|
"success": false,
|
|
"message": err.Error(),
|
|
})
|
|
return
|
|
}
|
|
c.JSON(200, gin.H{
|
|
"success": true,
|
|
"message": "重置模型倍率成功",
|
|
})
|
|
}
|