Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
new-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
b648b3cf
authored
May 05, 2025
by
tbphp
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: 缩进修复还原
parent
9e2af598
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
219 additions
and
220 deletions
+219
-220
middleware/model-rate-limit.go
+1
-2
model/option.go
+1
-2
web/src/components/RateLimitSetting.js
+44
-44
web/src/pages/Setting/RateLimit/SettingsRequestRateLimit.js
+173
-172
No files found.
middleware/model-rate-limit.go
View file @
b648b3cf
...
@@ -194,4 +194,4 @@ func ModelRequestRateLimit() func(c *gin.Context) {
...
@@ -194,4 +194,4 @@ func ModelRequestRateLimit() func(c *gin.Context) {
memoryRateLimitHandler
(
duration
,
totalMaxCount
,
successMaxCount
)(
c
)
memoryRateLimitHandler
(
duration
,
totalMaxCount
,
successMaxCount
)(
c
)
}
}
}
}
}
}
\ No newline at end of file
model/option.go
View file @
b648b3cf
...
@@ -402,4 +402,4 @@ func handleConfigUpdate(key, value string) bool {
...
@@ -402,4 +402,4 @@ func handleConfigUpdate(key, value string) bool {
config
.
UpdateConfigFromMap
(
cfg
,
configMap
)
config
.
UpdateConfigFromMap
(
cfg
,
configMap
)
return
true
// 已处理
return
true
// 已处理
}
}
\ No newline at end of file
web/src/components/RateLimitSetting.js
View file @
b648b3cf
...
@@ -9,62 +9,62 @@ import RequestRateLimit from '../pages/Setting/RateLimit/SettingsRequestRateLimi
...
@@ -9,62 +9,62 @@ import RequestRateLimit from '../pages/Setting/RateLimit/SettingsRequestRateLimi
const
RateLimitSetting
=
()
=>
{
const
RateLimitSetting
=
()
=>
{
const
{
t
}
=
useTranslation
();
const
{
t
}
=
useTranslation
();
let
[
inputs
,
setInputs
]
=
useState
({
let
[
inputs
,
setInputs
]
=
useState
({
ModelRequestRateLimitEnabled
:
false
,
ModelRequestRateLimitEnabled
:
false
,
ModelRequestRateLimitCount
:
0
,
ModelRequestRateLimitCount
:
0
,
ModelRequestRateLimitSuccessCount
:
1000
,
ModelRequestRateLimitSuccessCount
:
1000
,
ModelRequestRateLimitDurationMinutes
:
1
,
ModelRequestRateLimitDurationMinutes
:
1
,
ModelRequestRateLimitGroup
:
''
,
ModelRequestRateLimitGroup
:
''
,
});
});
let
[
loading
,
setLoading
]
=
useState
(
false
);
let
[
loading
,
setLoading
]
=
useState
(
false
);
const
getOptions
=
async
()
=>
{
const
getOptions
=
async
()
=>
{
const
res
=
await
API
.
get
(
'/api/option/'
);
const
res
=
await
API
.
get
(
'/api/option/'
);
const
{
success
,
message
,
data
}
=
res
.
data
;
const
{
success
,
message
,
data
}
=
res
.
data
;
if
(
success
)
{
if
(
success
)
{
let
newInputs
=
{};
let
newInputs
=
{};
data
.
forEach
((
item
)
=>
{
data
.
forEach
((
item
)
=>
{
if
(
item
.
key
===
'ModelRequestRateLimitGroup'
)
{
if
(
item
.
key
===
'ModelRequestRateLimitGroup'
)
{
item
.
value
=
JSON
.
stringify
(
JSON
.
parse
(
item
.
value
),
null
,
2
);
item
.
value
=
JSON
.
stringify
(
JSON
.
parse
(
item
.
value
),
null
,
2
);
}
}
if
(
item
.
key
.
endsWith
(
'Enabled'
))
{
if
(
item
.
key
.
endsWith
(
'Enabled'
))
{
newInputs
[
item
.
key
]
=
item
.
value
===
'true'
?
true
:
false
;
newInputs
[
item
.
key
]
=
item
.
value
===
'true'
?
true
:
false
;
}
else
{
}
else
{
newInputs
[
item
.
key
]
=
item
.
value
;
newInputs
[
item
.
key
]
=
item
.
value
;
}
}
});
});
setInputs
(
newInputs
);
setInputs
(
newInputs
);
}
else
{
}
else
{
showError
(
message
);
showError
(
message
);
}
}
};
};
async
function
onRefresh
()
{
async
function
onRefresh
()
{
try
{
try
{
setLoading
(
true
);
setLoading
(
true
);
await
getOptions
();
await
getOptions
();
// showSuccess('刷新成功');
// showSuccess('刷新成功');
}
catch
(
error
)
{
}
catch
(
error
)
{
showError
(
'刷新失败'
);
showError
(
'刷新失败'
);
}
finally
{
}
finally
{
setLoading
(
false
);
setLoading
(
false
);
}
}
}
}
useEffect
(()
=>
{
useEffect
(()
=>
{
onRefresh
();
onRefresh
();
},
[]);
},
[]);
return
(
return
(
<>
<>
<
Spin
spinning
=
{
loading
}
size
=
'large'
>
<
Spin
spinning
=
{
loading
}
size
=
'large'
>
{
/* AI请求速率限制 */
}
{
/* AI请求速率限制 */
}
<
Card
style
=
{{
marginTop
:
'10px'
}}
>
<
Card
style
=
{{
marginTop
:
'10px'
}}
>
<
RequestRateLimit
options
=
{
inputs
}
refresh
=
{
onRefresh
}
/
>
<
RequestRateLimit
options
=
{
inputs
}
refresh
=
{
onRefresh
}
/
>
<
/Card
>
<
/Card
>
<
/Spin
>
<
/Spin
>
<
/
>
<
/
>
);
);
};
};
...
...
web/src/pages/Setting/RateLimit/SettingsRequestRateLimit.js
View file @
b648b3cf
...
@@ -15,190 +15,190 @@ export default function RequestRateLimit(props) {
...
@@ -15,190 +15,190 @@ export default function RequestRateLimit(props) {
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
inputs
,
setInputs
]
=
useState
({
const
[
inputs
,
setInputs
]
=
useState
({
ModelRequestRateLimitEnabled
:
false
,
ModelRequestRateLimitEnabled
:
false
,
ModelRequestRateLimitCount
:
-
1
,
ModelRequestRateLimitCount
:
-
1
,
ModelRequestRateLimitSuccessCount
:
1000
,
ModelRequestRateLimitSuccessCount
:
1000
,
ModelRequestRateLimitDurationMinutes
:
1
,
ModelRequestRateLimitDurationMinutes
:
1
,
ModelRequestRateLimitGroup
:
''
,
ModelRequestRateLimitGroup
:
''
,
});
});
const
refForm
=
useRef
();
const
refForm
=
useRef
();
const
[
inputsRow
,
setInputsRow
]
=
useState
(
inputs
);
const
[
inputsRow
,
setInputsRow
]
=
useState
(
inputs
);
function
onSubmit
()
{
function
onSubmit
()
{
const
updateArray
=
compareObjects
(
inputs
,
inputsRow
);
const
updateArray
=
compareObjects
(
inputs
,
inputsRow
);
if
(
!
updateArray
.
length
)
return
showWarning
(
t
(
'你似乎并没有修改什么'
));
if
(
!
updateArray
.
length
)
return
showWarning
(
t
(
'你似乎并没有修改什么'
));
const
requestQueue
=
updateArray
.
map
((
item
)
=>
{
const
requestQueue
=
updateArray
.
map
((
item
)
=>
{
let
value
=
''
;
let
value
=
''
;
if
(
typeof
inputs
[
item
.
key
]
===
'boolean'
)
{
if
(
typeof
inputs
[
item
.
key
]
===
'boolean'
)
{
value
=
String
(
inputs
[
item
.
key
]);
value
=
String
(
inputs
[
item
.
key
]);
}
else
{
}
else
{
value
=
inputs
[
item
.
key
];
value
=
inputs
[
item
.
key
];
}
}
return
API
.
put
(
'/api/option/'
,
{
return
API
.
put
(
'/api/option/'
,
{
key
:
item
.
key
,
key
:
item
.
key
,
value
,
value
,
});
});
});
});
setLoading
(
true
);
setLoading
(
true
);
Promise
.
all
(
requestQueue
)
Promise
.
all
(
requestQueue
)
.
then
((
res
)
=>
{
.
then
((
res
)
=>
{
if
(
requestQueue
.
length
===
1
)
{
if
(
requestQueue
.
length
===
1
)
{
if
(
res
.
includes
(
undefined
))
return
;
if
(
res
.
includes
(
undefined
))
return
;
}
else
if
(
requestQueue
.
length
>
1
)
{
}
else
if
(
requestQueue
.
length
>
1
)
{
if
(
res
.
includes
(
undefined
))
if
(
res
.
includes
(
undefined
))
return
showError
(
t
(
'部分保存失败,请重试'
));
return
showError
(
t
(
'部分保存失败,请重试'
));
}
}
for
(
let
i
=
0
;
i
<
res
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
res
.
length
;
i
++
)
{
if
(
!
res
[
i
].
data
.
success
)
{
if
(
!
res
[
i
].
data
.
success
)
{
return
showError
(
res
[
i
].
data
.
message
);
return
showError
(
res
[
i
].
data
.
message
);
}
}
}
}
showSuccess
(
t
(
'保存成功'
));
showSuccess
(
t
(
'保存成功'
));
props
.
refresh
();
props
.
refresh
();
})
})
.
catch
(()
=>
{
.
catch
(()
=>
{
showError
(
t
(
'保存失败,请重试'
));
showError
(
t
(
'保存失败,请重试'
));
})
})
.
finally
(()
=>
{
.
finally
(()
=>
{
setLoading
(
false
);
setLoading
(
false
);
});
});
}
}
useEffect
(()
=>
{
useEffect
(()
=>
{
const
currentInputs
=
{};
const
currentInputs
=
{};
for
(
let
key
in
props
.
options
)
{
for
(
let
key
in
props
.
options
)
{
if
(
Object
.
keys
(
inputs
).
includes
(
key
))
{
if
(
Object
.
keys
(
inputs
).
includes
(
key
))
{
currentInputs
[
key
]
=
props
.
options
[
key
];
currentInputs
[
key
]
=
props
.
options
[
key
];
}
}
}
}
setInputs
(
currentInputs
);
setInputs
(
currentInputs
);
setInputsRow
(
structuredClone
(
currentInputs
));
setInputsRow
(
structuredClone
(
currentInputs
));
refForm
.
current
.
setValues
(
currentInputs
);
refForm
.
current
.
setValues
(
currentInputs
);
},
[
props
.
options
]);
},
[
props
.
options
]);
return
(
return
(
<>
<>
<
Spin
spinning
=
{
loading
}
>
<
Spin
spinning
=
{
loading
}
>
<
Form
<
Form
values
=
{
inputs
}
values
=
{
inputs
}
getFormApi
=
{(
formAPI
)
=>
(
refForm
.
current
=
formAPI
)}
getFormApi
=
{(
formAPI
)
=>
(
refForm
.
current
=
formAPI
)}
style
=
{{
marginBottom
:
15
}}
style
=
{{
marginBottom
:
15
}}
>
>
<
Form
.
Section
text
=
{
t
(
'模型请求速率限制'
)}
>
<
Form
.
Section
text
=
{
t
(
'模型请求速率限制'
)}
>
<
Row
gutter
=
{
16
}
>
<
Row
gutter
=
{
16
}
>
<
Col
xs
=
{
24
}
sm
=
{
12
}
md
=
{
8
}
lg
=
{
8
}
xl
=
{
8
}
>
<
Col
xs
=
{
24
}
sm
=
{
12
}
md
=
{
8
}
lg
=
{
8
}
xl
=
{
8
}
>
<
Form
.
Switch
<
Form
.
Switch
field
=
{
'ModelRequestRateLimitEnabled'
}
field
=
{
'ModelRequestRateLimitEnabled'
}
label
=
{
t
(
'启用用户模型请求速率限制(可能会影响高并发性能)'
)}
label
=
{
t
(
'启用用户模型请求速率限制(可能会影响高并发性能)'
)}
size
=
'default'
size
=
'default'
checkedText
=
'|'
checkedText
=
'|'
uncheckedText
=
'〇'
uncheckedText
=
'〇'
onChange
=
{(
value
)
=>
{
onChange
=
{(
value
)
=>
{
setInputs
({
setInputs
({
...
inputs
,
...
inputs
,
ModelRequestRateLimitEnabled
:
value
,
ModelRequestRateLimitEnabled
:
value
,
});
});
}}
}}
/
>
/
>
<
/Col
>
<
/Col
>
<
/Row
>
<
/Row
>
<
Row
>
<
Row
>
<
Col
xs
=
{
24
}
sm
=
{
12
}
md
=
{
8
}
lg
=
{
8
}
xl
=
{
8
}
>
<
Col
xs
=
{
24
}
sm
=
{
12
}
md
=
{
8
}
lg
=
{
8
}
xl
=
{
8
}
>
<
Form
.
InputNumber
<
Form
.
InputNumber
label
=
{
t
(
'限制周期'
)}
label
=
{
t
(
'限制周期'
)}
step
=
{
1
}
step
=
{
1
}
min
=
{
0
}
min
=
{
0
}
suffix
=
{
t
(
'分钟'
)}
suffix
=
{
t
(
'分钟'
)}
extraText
=
{
t
(
'频率限制的周期(分钟)'
)}
extraText
=
{
t
(
'频率限制的周期(分钟)'
)}
field
=
{
'ModelRequestRateLimitDurationMinutes'
}
field
=
{
'ModelRequestRateLimitDurationMinutes'
}
onChange
=
{(
value
)
=>
onChange
=
{(
value
)
=>
setInputs
({
setInputs
({
...
inputs
,
...
inputs
,
ModelRequestRateLimitDurationMinutes
:
String
(
value
),
ModelRequestRateLimitDurationMinutes
:
String
(
value
),
})
})
}
}
/
>
/
>
<
/Col
>
<
/Col
>
<
/Row
>
<
/Row
>
<
Row
>
<
Row
>
<
Col
xs
=
{
24
}
sm
=
{
12
}
md
=
{
8
}
lg
=
{
8
}
xl
=
{
8
}
>
<
Col
xs
=
{
24
}
sm
=
{
12
}
md
=
{
8
}
lg
=
{
8
}
xl
=
{
8
}
>
<
Form
.
InputNumber
<
Form
.
InputNumber
label
=
{
t
(
'用户每周期最多请求次数'
)}
label
=
{
t
(
'用户每周期最多请求次数'
)}
step
=
{
1
}
step
=
{
1
}
min
=
{
0
}
min
=
{
0
}
suffix
=
{
t
(
'次'
)}
suffix
=
{
t
(
'次'
)}
extraText
=
{
t
(
'包括失败请求的次数,0代表不限制'
)}
extraText
=
{
t
(
'包括失败请求的次数,0代表不限制'
)}
field
=
{
'ModelRequestRateLimitCount'
}
field
=
{
'ModelRequestRateLimitCount'
}
onChange
=
{(
value
)
=>
onChange
=
{(
value
)
=>
setInputs
({
setInputs
({
...
inputs
,
...
inputs
,
ModelRequestRateLimitCount
:
String
(
value
),
ModelRequestRateLimitCount
:
String
(
value
),
})
})
}
}
/
>
/
>
<
/Col
>
<
/Col
>
<
Col
xs
=
{
24
}
sm
=
{
12
}
md
=
{
8
}
lg
=
{
8
}
xl
=
{
8
}
>
<
Col
xs
=
{
24
}
sm
=
{
12
}
md
=
{
8
}
lg
=
{
8
}
xl
=
{
8
}
>
<
Form
.
InputNumber
<
Form
.
InputNumber
label
=
{
t
(
'用户每周期最多请求完成次数'
)}
label
=
{
t
(
'用户每周期最多请求完成次数'
)}
step
=
{
1
}
step
=
{
1
}
min
=
{
1
}
min
=
{
1
}
suffix
=
{
t
(
'次'
)}
suffix
=
{
t
(
'次'
)}
extraText
=
{
t
(
'只包括请求成功的次数'
)}
extraText
=
{
t
(
'只包括请求成功的次数'
)}
field
=
{
'ModelRequestRateLimitSuccessCount'
}
field
=
{
'ModelRequestRateLimitSuccessCount'
}
onChange
=
{(
value
)
=>
onChange
=
{(
value
)
=>
setInputs
({
setInputs
({
...
inputs
,
...
inputs
,
ModelRequestRateLimitSuccessCount
:
String
(
value
),
ModelRequestRateLimitSuccessCount
:
String
(
value
),
})
})
}
}
/
>
/
>
<
/Col
>
<
/Col
>
<
/Row
>
<
/Row
>
<
Row
>
<
Row
>
<
Col
xs
=
{
24
}
sm
=
{
16
}
>
<
Col
xs
=
{
24
}
sm
=
{
16
}
>
<
Form
.
TextArea
<
Form
.
TextArea
label
=
{
t
(
'分组速率限制'
)}
label
=
{
t
(
'分组速率限制'
)}
placeholder
=
{
t
(
placeholder
=
{
t
(
'{\n "default": [200, 100],\n "vip": [0, 1000]\n}'
,
'{\n "default": [200, 100],\n "vip": [0, 1000]\n}'
,
)}
)}
field
=
{
'ModelRequestRateLimitGroup'
}
field
=
{
'ModelRequestRateLimitGroup'
}
autosize
=
{{
minRows
:
5
,
maxRows
:
15
}}
autosize
=
{{
minRows
:
5
,
maxRows
:
15
}}
trigger
=
'blur'
trigger
=
'blur'
stopValidateWithError
stopValidateWithError
rules
=
{[
rules
=
{[
{
{
validator
:
(
rule
,
value
)
=>
verifyJSON
(
value
),
validator
:
(
rule
,
value
)
=>
verifyJSON
(
value
),
message
:
t
(
'不是合法的 JSON 字符串'
),
message
:
t
(
'不是合法的 JSON 字符串'
),
},
},
]}
]}
extraText
=
{
extraText
=
{
<
div
>
<
div
>
<
p
style
=
{{
marginBottom
:
-
15
}}
>
{
t
(
'说明:'
)}
<
/p
>
<
p
style
=
{{
marginBottom
:
-
15
}}
>
{
t
(
'说明:'
)}
<
/p
>
<
ul
>
<
ul
>
<
li
>
{
t
(
'使用 JSON 对象格式,格式为:{"组名": [最多请求次数, 最多请求完成次数]}'
)}
<
/li
>
<
li
>
{
t
(
'使用 JSON 对象格式,格式为:{"组名": [最多请求次数, 最多请求完成次数]}'
)}
<
/li
>
<
li
>
{
t
(
'示例:{"default": [200, 100], "vip": [0, 1000]}。'
)}
<
/li
>
<
li
>
{
t
(
'示例:{"default": [200, 100], "vip": [0, 1000]}。'
)}
<
/li
>
<
li
>
{
t
(
'[最多请求次数]必须大于等于0,[最多请求完成次数]必须大于等于1。'
)}
<
/li
>
<
li
>
{
t
(
'[最多请求次数]必须大于等于0,[最多请求完成次数]必须大于等于1。'
)}
<
/li
>
<
li
>
{
t
(
'分组速率配置优先级高于全局速率限制。'
)}
<
/li
>
<
li
>
{
t
(
'分组速率配置优先级高于全局速率限制。'
)}
<
/li
>
<
li
>
{
t
(
'限制周期统一使用上方配置的“限制周期”值。'
)}
<
/li
>
<
li
>
{
t
(
'限制周期统一使用上方配置的“限制周期”值。'
)}
<
/li
>
<
/ul
>
<
/ul
>
<
/div
>
<
/div
>
}
}
onChange
=
{(
value
)
=>
{
onChange
=
{(
value
)
=>
{
setInputs
({
...
inputs
,
ModelRequestRateLimitGroup
:
value
});
setInputs
({
...
inputs
,
ModelRequestRateLimitGroup
:
value
});
}}
}}
/
>
/
>
<
/Col
>
<
/Col
>
<
/Row
>
<
/Row
>
<
Row
>
<
Row
>
<
Button
size
=
'default'
onClick
=
{
onSubmit
}
>
<
Button
size
=
'default'
onClick
=
{
onSubmit
}
>
{
t
(
'保存模型速率限制'
)}
{
t
(
'保存模型速率限制'
)}
<
/Button
>
<
/Button
>
<
/Row
>
<
/Row
>
<
/Form.Section
>
<
/Form.Section
>
<
/Form
>
<
/Form
>
<
/Spin
>
<
/Spin
>
<
/
>
<
/
>
);
);
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment