diff --git a/controller/channel-test.go b/controller/channel-test.go
index f9657edb..2ae8b0ef 100644
--- a/controller/channel-test.go
+++ b/controller/channel-test.go
@@ -193,6 +193,7 @@ func testChannel(channel *model.Channel, testModel string, endpointType string)
}
}
+ info.IsChannelTest = true
info.InitChannelMeta(c)
err = helper.ModelMappedHelper(c, info, request)
@@ -309,6 +310,27 @@ func testChannel(channel *model.Channel, testModel string, endpointType string)
newAPIError: types.NewError(err, types.ErrorCodeJsonMarshalFailed),
}
}
+
+ //jsonData, err = relaycommon.RemoveDisabledFields(jsonData, info.ChannelOtherSettings)
+ //if err != nil {
+ // return testResult{
+ // context: c,
+ // localErr: err,
+ // newAPIError: types.NewError(err, types.ErrorCodeConvertRequestFailed),
+ // }
+ //}
+
+ if len(info.ParamOverride) > 0 {
+ jsonData, err = relaycommon.ApplyParamOverride(jsonData, info.ParamOverride, relaycommon.BuildParamOverrideContext(info))
+ if err != nil {
+ return testResult{
+ context: c,
+ localErr: err,
+ newAPIError: types.NewError(err, types.ErrorCodeChannelParamOverrideInvalid),
+ }
+ }
+ }
+
requestBody := bytes.NewBuffer(jsonData)
c.Request.Body = io.NopCloser(requestBody)
resp, err := adaptor.DoRequest(c, info, requestBody)
diff --git a/relay/common/override.go b/relay/common/override.go
index 872c960f..1a0c2478 100644
--- a/relay/common/override.go
+++ b/relay/common/override.go
@@ -570,18 +570,19 @@ func mergeObjects(jsonStr, path string, value interface{}, keepOrigin bool) (str
// BuildParamOverrideContext 提供 ApplyParamOverride 可用的上下文信息。
// 目前内置以下字段:
-// - model:优先使用上游模型名(UpstreamModelName),若不存在则回落到原始模型名(OriginModelName)。
-// - upstream_model:始终为通道映射后的上游模型名。
+// - upstream_model/model:始终为通道映射后的上游模型名。
// - original_model:请求最初指定的模型名。
+// - request_path:请求路径
+// - is_channel_test:是否为渠道测试请求(同 is_test)。
func BuildParamOverrideContext(info *RelayInfo) map[string]interface{} {
- if info == nil || info.ChannelMeta == nil {
+ if info == nil {
return nil
}
ctx := make(map[string]interface{})
- if info.UpstreamModelName != "" {
- ctx["model"] = info.UpstreamModelName
- ctx["upstream_model"] = info.UpstreamModelName
+ if info.ChannelMeta != nil && info.ChannelMeta.UpstreamModelName != "" {
+ ctx["model"] = info.ChannelMeta.UpstreamModelName
+ ctx["upstream_model"] = info.ChannelMeta.UpstreamModelName
}
if info.OriginModelName != "" {
ctx["original_model"] = info.OriginModelName
@@ -590,8 +591,13 @@ func BuildParamOverrideContext(info *RelayInfo) map[string]interface{} {
}
}
- if len(ctx) == 0 {
- return nil
+ if info.RequestURLPath != "" {
+ requestPath := info.RequestURLPath
+ if requestPath != "" {
+ ctx["request_path"] = requestPath
+ }
}
+
+ ctx["is_channel_test"] = info.IsChannelTest
return ctx
}
diff --git a/relay/common/relay_info.go b/relay/common/relay_info.go
index 1b9762fe..56f16fbf 100644
--- a/relay/common/relay_info.go
+++ b/relay/common/relay_info.go
@@ -115,6 +115,7 @@ type RelayInfo struct {
SendResponseCount int
FinalPreConsumedQuota int // 最终预消耗的配额
IsClaudeBetaQuery bool // /v1/messages?beta=true
+ IsChannelTest bool // channel test request
PriceData types.PriceData
diff --git a/web/src/components/table/channels/modals/EditChannelModal.jsx b/web/src/components/table/channels/modals/EditChannelModal.jsx
index 0abd3fdf..722c1e8a 100644
--- a/web/src/components/table/channels/modals/EditChannelModal.jsx
+++ b/web/src/components/table/channels/modals/EditChannelModal.jsx
@@ -199,17 +199,11 @@ const EditChannelModal = (props) => {
if (!trimmed) return [];
try {
const parsed = JSON.parse(trimmed);
- if (
- !parsed ||
- typeof parsed !== 'object' ||
- Array.isArray(parsed)
- ) {
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
return [];
}
const values = Object.values(parsed)
- .map((value) =>
- typeof value === 'string' ? value.trim() : undefined,
- )
+ .map((value) => (typeof value === 'string' ? value.trim() : undefined))
.filter((value) => value);
return Array.from(new Set(values));
} catch (error) {
@@ -509,6 +503,18 @@ const EditChannelModal = (props) => {
//setAutoBan
};
+ const formatJsonField = (fieldName) => {
+ const rawValue = (inputs?.[fieldName] ?? '').trim();
+ if (!rawValue) return;
+
+ try {
+ const parsed = JSON.parse(rawValue);
+ handleInputChange(fieldName, JSON.stringify(parsed, null, 2));
+ } catch (error) {
+ showError(`${t('JSON格式错误')}: ${error.message}`);
+ }
+ };
+
const loadChannel = async () => {
setLoading(true);
let res = await API.get(`/api/channel/${channelId}`);
@@ -2812,6 +2818,12 @@ const EditChannelModal = (props) => {
>
{t('新格式模板')}
+