Skip to content

Commit fe37c66

Browse files
authored
Merge pull request #105 from xunxun1982/xxdev
fix: 修复动态权重浮动提示显示不全的问题
2 parents 0d796f1 + 37c0092 commit fe37c66

File tree

7 files changed

+91
-65
lines changed

7 files changed

+91
-65
lines changed

internal/channel/codex_channel_test.go

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -194,39 +194,39 @@ func TestForceStreamRequest(t *testing.T) {
194194
t.Parallel()
195195

196196
tests := []struct {
197-
name string
198-
inputBody string
199-
expectedModified bool
200-
expectedStreamValue bool
201-
shouldContainStream bool
197+
name string
198+
inputBody string
199+
expectedModified bool
200+
expectedStreamValue bool
201+
shouldContainStream bool
202202
}{
203203
{
204-
name: "Non-streaming request becomes streaming",
205-
inputBody: `{"model": "gpt-5.2-codex", "input": "test"}`,
206-
expectedModified: true,
207-
expectedStreamValue: true,
208-
shouldContainStream: true,
204+
name: "Non-streaming request becomes streaming",
205+
inputBody: `{"model": "gpt-5.2-codex", "input": "test"}`,
206+
expectedModified: true,
207+
expectedStreamValue: true,
208+
shouldContainStream: true,
209209
},
210210
{
211-
name: "Already streaming request unchanged",
212-
inputBody: `{"model": "gpt-5.2-codex", "stream": true}`,
213-
expectedModified: false,
214-
expectedStreamValue: true,
215-
shouldContainStream: true,
211+
name: "Already streaming request unchanged",
212+
inputBody: `{"model": "gpt-5.2-codex", "stream": true}`,
213+
expectedModified: false,
214+
expectedStreamValue: true,
215+
shouldContainStream: true,
216216
},
217217
{
218-
name: "Empty body unchanged",
219-
inputBody: ``,
220-
expectedModified: false,
221-
expectedStreamValue: false,
222-
shouldContainStream: false,
218+
name: "Empty body unchanged",
219+
inputBody: ``,
220+
expectedModified: false,
221+
expectedStreamValue: false,
222+
shouldContainStream: false,
223223
},
224224
{
225-
name: "Invalid JSON unchanged",
226-
inputBody: `{invalid}`,
227-
expectedModified: false,
228-
expectedStreamValue: false,
229-
shouldContainStream: false,
225+
name: "Invalid JSON unchanged",
226+
inputBody: `{invalid}`,
227+
expectedModified: false,
228+
expectedStreamValue: false,
229+
shouldContainStream: false,
230230
},
231231
}
232232

internal/handler/group_import_export_handler.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ type GroupExportInfo struct {
4949
ParamOverrides map[string]any `json:"param_overrides"`
5050
Config map[string]any `json:"config"`
5151
HeaderRules []models.HeaderRule `json:"header_rules"`
52-
ModelMapping string `json:"model_mapping,omitempty"` // Deprecated: for backward compatibility
53-
ModelRedirectRules map[string]string `json:"model_redirect_rules,omitempty"` // V1 rules (one-to-one)
52+
ModelMapping string `json:"model_mapping,omitempty"` // Deprecated: for backward compatibility
53+
ModelRedirectRules map[string]string `json:"model_redirect_rules,omitempty"` // V1 rules (one-to-one)
5454
ModelRedirectRulesV2 json.RawMessage `json:"model_redirect_rules_v2,omitempty"` // V2 rules (one-to-many)
55-
ModelRedirectStrict bool `json:"model_redirect_strict,omitempty"` // Strict mode
56-
PathRedirects []models.PathRedirectRule `json:"path_redirects,omitempty"` // Path redirect rules
55+
ModelRedirectStrict bool `json:"model_redirect_strict,omitempty"` // Strict mode
56+
PathRedirects []models.PathRedirectRule `json:"path_redirects,omitempty"` // Path redirect rules
5757
ProxyKeys string `json:"proxy_keys"`
5858
Sort int `json:"sort"`
5959
}

internal/handler/task_handler.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ var (
3030
// get returns cached status if valid, otherwise returns nil
3131
// Returns a copy to prevent callers from mutating cached data
3232
// Note: Shallow copy is safe because:
33-
// 1. Result field stores value-only structs (KeyImportResult, KeyDeleteResult, ManualValidationResult)
34-
// All these types contain only primitive fields (int, string) with no reference types
35-
// 2. FinishedAt is *time.Time, but time.Time is immutable - copying the pointer is safe
36-
// 3. All other fields (string, bool, int, time.Time) are value types
33+
// 1. Result field stores value-only structs (KeyImportResult, KeyDeleteResult, ManualValidationResult)
34+
// All these types contain only primitive fields (int, string) with no reference types
35+
// 2. FinishedAt is *time.Time, but time.Time is immutable - copying the pointer is safe
36+
// 3. All other fields (string, bool, int, time.Time) are value types
3737
func (c *taskStatusCache) get() *services.TaskStatus {
3838
c.mu.RLock()
3939
defer c.mu.RUnlock()

internal/proxy/cc_support.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,6 +1596,7 @@ var reWindowsDrivePath = regexp.MustCompile(`[A-Za-z]:`)
15961596
// Examples:
15971597
// - F:\test\file.py - the \t and \f are path separators, not escape sequences
15981598
// - C:\new\readme.txt - the \n and \r are path separators, not escape sequences
1599+
//
15991600
// Pattern: Match any single backslash (not already doubled)
16001601
// Strategy: Match \ that is NOT followed by another \ (to avoid matching already-doubled \\)
16011602
var reWindowsPathBackslash = regexp.MustCompile(`\\(?:[^\\]|$)`)

internal/proxy/cc_support_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7028,13 +7028,13 @@ func TestConvertWindowsPathsInToolResult_CorruptedPaths(t *testing.T) {
70287028
}{
70297029
{
70307030
name: "path with tab character (\\t interpreted)",
7031-
input: "F:MyProjects" + string(rune(9)) + "test", // tab character (byte 9)
7032-
expected: "F:/MyProjects/test", // Should reconstruct with slashes
7031+
input: "F:MyProjects" + string(rune(9)) + "test", // tab character (byte 9)
7032+
expected: "F:/MyProjects/test", // Should reconstruct with slashes
70337033
},
70347034
{
70357035
name: "path with newline character (\\n interpreted)",
7036-
input: "F:MyProjects" + string(rune(10)) + "new", // newline character (byte 10)
7037-
expected: "F:/MyProjects/new", // Should reconstruct with slashes
7036+
input: "F:MyProjects" + string(rune(10)) + "new", // newline character (byte 10)
7037+
expected: "F:/MyProjects/new", // Should reconstruct with slashes
70387038
},
70397039
{
70407040
name: "path with multiple control chars",
@@ -7053,8 +7053,8 @@ func TestConvertWindowsPathsInToolResult_CorruptedPaths(t *testing.T) {
70537053
},
70547054
{
70557055
name: "path with form feed character (\\f interpreted)",
7056-
input: "F:" + string(rune(12)) + "older", // form feed character (byte 12)
7057-
expected: "F:/older", // Should reconstruct with slash
7056+
input: "F:" + string(rune(12)) + "older", // form feed character (byte 12)
7057+
expected: "F:/older", // Should reconstruct with slash
70587058
},
70597059
{
70607060
name: "Unix path unchanged",
@@ -7068,8 +7068,8 @@ func TestConvertWindowsPathsInToolResult_CorruptedPaths(t *testing.T) {
70687068
},
70697069
{
70707070
name: "path with backspace character (\\b interpreted)",
7071-
input: "D:" + string(rune(8)) + "backup", // backspace character (byte 8)
7072-
expected: "D:/backup", // Should reconstruct with slash
7071+
input: "D:" + string(rune(8)) + "backup", // backspace character (byte 8)
7072+
expected: "D:/backup", // Should reconstruct with slash
70737073
},
70747074
}
70757075

internal/services/import_export_service.go

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -540,16 +540,16 @@ func (s *ImportExportService) ExportGroup(groupID uint) (*GroupExportData, error
540540
result.ChildGroups = make([]ChildGroupExport, 0, len(childGroups))
541541
for _, cg := range childGroups {
542542
childExport := ChildGroupExport{
543-
Name: cg.Name,
544-
DisplayName: cg.DisplayName,
545-
Description: cg.Description,
546-
Enabled: cg.Enabled,
547-
ProxyKeys: cg.ProxyKeys,
548-
Sort: cg.Sort,
549-
TestModel: cg.TestModel,
550-
ModelMapping: cg.ModelMapping,
551-
ModelRedirectStrict: cg.ModelRedirectStrict,
552-
Keys: childKeysMap[cg.ID],
543+
Name: cg.Name,
544+
DisplayName: cg.DisplayName,
545+
Description: cg.Description,
546+
Enabled: cg.Enabled,
547+
ProxyKeys: cg.ProxyKeys,
548+
Sort: cg.Sort,
549+
TestModel: cg.TestModel,
550+
ModelMapping: cg.ModelMapping,
551+
ModelRedirectStrict: cg.ModelRedirectStrict,
552+
Keys: childKeysMap[cg.ID],
553553
}
554554

555555
// Export JSON fields as raw JSON to preserve structure
@@ -752,19 +752,19 @@ func (s *ImportExportService) importChildGroups(tx *gorm.DB, parentGroupID uint,
752752

753753
// Create child group with inherited channel_type from parent
754754
childGroup := models.Group{
755-
Name: childName,
756-
DisplayName: childData.DisplayName,
757-
Description: childData.Description,
758-
GroupType: "standard",
759-
ChannelType: parentChannelType, // Inherit from parent
760-
Enabled: childData.Enabled,
761-
ParentGroupID: &parentGroupID,
762-
ProxyKeys: childData.ProxyKeys,
763-
Sort: childData.Sort,
764-
Upstreams: []byte(upstreamsJSON),
765-
TestModel: testModel, // Use fallback if empty
766-
ModelMapping: childData.ModelMapping,
767-
ModelRedirectStrict: childData.ModelRedirectStrict,
755+
Name: childName,
756+
DisplayName: childData.DisplayName,
757+
Description: childData.Description,
758+
GroupType: "standard",
759+
ChannelType: parentChannelType, // Inherit from parent
760+
Enabled: childData.Enabled,
761+
ParentGroupID: &parentGroupID,
762+
ProxyKeys: childData.ProxyKeys,
763+
Sort: childData.Sort,
764+
Upstreams: []byte(upstreamsJSON),
765+
TestModel: testModel, // Use fallback if empty
766+
ModelMapping: childData.ModelMapping,
767+
ModelRedirectStrict: childData.ModelRedirectStrict,
768768
}
769769

770770
// Import JSON fields from exported data

web/src/components/keys/GroupFormModal.vue

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,10 @@ function mergeModelRedirectItems(items: ModelRedirectItemV2[]): ModelRedirectIte
803803
804804
if (mergedMap.has(from)) {
805805
// Merge targets into existing rule
806-
const existing = mergedMap.get(from)!;
806+
const existing = mergedMap.get(from);
807+
if (!existing) {
808+
continue;
809+
}
807810
// Normalize existing target models before dedupe to avoid whitespace duplicates
808811
const seenModels = new Set(existing.targets.map(t => t.model.trim()));
809812
@@ -2937,20 +2940,42 @@ async function handleSubmit() {
29372940
/* Dynamic weight tooltip styles */
29382941
.dynamic-weight-tooltip {
29392942
min-width: 180px;
2943+
max-width: 320px;
2944+
padding: 4px 0;
2945+
word-break: break-word;
2946+
overflow-wrap: break-word;
29402947
}
29412948
29422949
.dynamic-weight-tooltip .tooltip-title {
29432950
font-weight: 600;
29442951
margin-bottom: 8px;
29452952
padding-bottom: 4px;
29462953
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
2954+
white-space: nowrap;
2955+
overflow: hidden;
2956+
text-overflow: ellipsis;
29472957
}
29482958
29492959
.dynamic-weight-tooltip .tooltip-row {
29502960
display: flex;
29512961
justify-content: space-between;
2962+
align-items: flex-start;
29522963
margin-bottom: 4px;
29532964
font-size: 12px;
2965+
gap: 12px;
2966+
line-height: 1.5;
2967+
}
2968+
2969+
.dynamic-weight-tooltip .tooltip-row > span:first-child {
2970+
flex-shrink: 0;
2971+
white-space: nowrap;
2972+
}
2973+
2974+
.dynamic-weight-tooltip .tooltip-row > span:last-child {
2975+
flex: 1;
2976+
text-align: right;
2977+
word-break: break-word;
2978+
overflow-wrap: break-word;
29542979
}
29552980
29562981
.dynamic-weight-tooltip .health-good {

0 commit comments

Comments
 (0)