@@ -92,12 +92,12 @@ func RedisDel(key string) error {
|
|||||||
return RDB.Del(ctx, key).Err()
|
return RDB.Del(ctx, key).Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
func RedisHDelObj(key string) error {
|
func RedisDelKey(key string) error {
|
||||||
if DebugEnabled {
|
if DebugEnabled {
|
||||||
SysLog(fmt.Sprintf("Redis HDEL: key=%s", key))
|
SysLog(fmt.Sprintf("Redis DEL Key: key=%s", key))
|
||||||
}
|
}
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
return RDB.HDel(ctx, key).Err()
|
return RDB.Del(ctx, key).Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
func RedisHSetObj(key string, obj interface{}, expiration time.Duration) error {
|
func RedisHSetObj(key string, obj interface{}, expiration time.Duration) error {
|
||||||
|
|||||||
@@ -623,3 +623,44 @@ func BatchSetChannelTag(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetTagModels(c *gin.Context) {
|
||||||
|
tag := c.Query("tag")
|
||||||
|
if tag == "" {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"success": false,
|
||||||
|
"message": "tag不能为空",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
channels, err := model.GetChannelsByTag(tag, false) // Assuming false for idSort is fine here
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
"success": false,
|
||||||
|
"message": err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var longestModels string
|
||||||
|
maxLength := 0
|
||||||
|
|
||||||
|
// Find the longest models string among all channels with the given tag
|
||||||
|
for _, channel := range channels {
|
||||||
|
if channel.Models != "" {
|
||||||
|
currentModels := strings.Split(channel.Models, ",")
|
||||||
|
if len(currentModels) > maxLength {
|
||||||
|
maxLength = len(currentModels)
|
||||||
|
longestModels = channel.Models
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"success": true,
|
||||||
|
"message": "",
|
||||||
|
"data": longestModels,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func cacheSetToken(token Token) error {
|
|||||||
|
|
||||||
func cacheDeleteToken(key string) error {
|
func cacheDeleteToken(key string) error {
|
||||||
key = common.GenerateHMAC(key)
|
key = common.GenerateHMAC(key)
|
||||||
err := common.RedisHDelObj(fmt.Sprintf("token:%s", key))
|
err := common.RedisDelKey(fmt.Sprintf("token:%s", key))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ package model
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"one-api/common"
|
"one-api/common"
|
||||||
"one-api/constant"
|
"one-api/constant"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
"github.com/bytedance/gopkg/util/gopool"
|
"github.com/bytedance/gopkg/util/gopool"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -57,7 +58,7 @@ func invalidateUserCache(userId int) error {
|
|||||||
if !common.RedisEnabled {
|
if !common.RedisEnabled {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return common.RedisHDelObj(getUserCacheKey(userId))
|
return common.RedisDelKey(getUserCacheKey(userId))
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateUserCache updates all user cache fields using hash
|
// updateUserCache updates all user cache fields using hash
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ func SetApiRouter(router *gin.Engine) {
|
|||||||
channelRoute.GET("/fetch_models/:id", controller.FetchUpstreamModels)
|
channelRoute.GET("/fetch_models/:id", controller.FetchUpstreamModels)
|
||||||
channelRoute.POST("/fetch_models", controller.FetchModels)
|
channelRoute.POST("/fetch_models", controller.FetchModels)
|
||||||
channelRoute.POST("/batch/tag", controller.BatchSetChannelTag)
|
channelRoute.POST("/batch/tag", controller.BatchSetChannelTag)
|
||||||
|
channelRoute.GET("/tag/models", controller.GetTagModels)
|
||||||
}
|
}
|
||||||
tokenRoute := apiRouter.Group("/token")
|
tokenRoute := apiRouter.Group("/token")
|
||||||
tokenRoute.Use(middleware.UserAuth())
|
tokenRoute.Use(middleware.UserAuth())
|
||||||
|
|||||||
@@ -462,7 +462,7 @@ const LogsTable = () => {
|
|||||||
percent={text ? parseInt(text.replace('%', '')) : 0}
|
percent={text ? parseInt(text.replace('%', '')) : 0}
|
||||||
showInfo={true}
|
showInfo={true}
|
||||||
aria-label='drawing progress'
|
aria-label='drawing progress'
|
||||||
style={{ minWidth: '200px' }}
|
style={{ minWidth: '160px' }}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@@ -483,6 +483,7 @@ const LogsTable = () => {
|
|||||||
setModalImageUrl(text);
|
setModalImageUrl(text);
|
||||||
setIsModalOpenurl(true);
|
setIsModalOpenurl(true);
|
||||||
}}
|
}}
|
||||||
|
className="!rounded-full"
|
||||||
>
|
>
|
||||||
{t('查看图片')}
|
{t('查看图片')}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -395,7 +395,7 @@ const LogsTable = () => {
|
|||||||
percent={text ? parseInt(text.replace('%', '')) : 0}
|
percent={text ? parseInt(text.replace('%', '')) : 0}
|
||||||
showInfo={true}
|
showInfo={true}
|
||||||
aria-label='task progress'
|
aria-label='task progress'
|
||||||
style={{ minWidth: '200px' }}
|
style={{ minWidth: '160px' }}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
import { BrowserRouter } from 'react-router-dom';
|
import { BrowserRouter } from 'react-router-dom';
|
||||||
|
import '@douyinfe/semi-ui/dist/css/semi.css';
|
||||||
import { UserProvider } from './context/User';
|
import { UserProvider } from './context/User';
|
||||||
import 'react-toastify/dist/ReactToastify.css';
|
import 'react-toastify/dist/ReactToastify.css';
|
||||||
import { StatusProvider } from './context/Status';
|
import { StatusProvider } from './context/Status';
|
||||||
|
|||||||
@@ -194,6 +194,24 @@ const EditTagModal = (props) => {
|
|||||||
}, [originModelOptions, inputs.models]);
|
}, [originModelOptions, inputs.models]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const fetchTagModels = async () => {
|
||||||
|
if (!tag) return;
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const res = await API.get(`/api/channel/tag/models?tag=${tag}`);
|
||||||
|
if (res?.data?.success) {
|
||||||
|
const models = res.data.data ? res.data.data.split(',') : [];
|
||||||
|
setInputs((inputs) => ({ ...inputs, models: models }));
|
||||||
|
} else {
|
||||||
|
showError(res.data.message);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
showError(error.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
setInputs({
|
setInputs({
|
||||||
...originInputs,
|
...originInputs,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
@@ -201,7 +219,8 @@ const EditTagModal = (props) => {
|
|||||||
});
|
});
|
||||||
fetchModels().then();
|
fetchModels().then();
|
||||||
fetchGroups().then();
|
fetchGroups().then();
|
||||||
}, [visible]);
|
fetchTagModels().then(); // Call the new function
|
||||||
|
}, [visible, tag]); // Add tag to dependency array
|
||||||
|
|
||||||
const addCustomModels = () => {
|
const addCustomModels = () => {
|
||||||
if (customModel.trim() === '') return;
|
if (customModel.trim() === '') return;
|
||||||
@@ -347,6 +366,11 @@ const EditTagModal = (props) => {
|
|||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<Text strong className="block mb-2">{t('模型')}</Text>
|
<Text strong className="block mb-2">{t('模型')}</Text>
|
||||||
|
<Banner
|
||||||
|
type="info"
|
||||||
|
description={t('当前模型列表为该标签下所有渠道模型列表最长的一个,并非所有渠道的并集,请注意可能导致某些渠道模型丢失。')}
|
||||||
|
className="!rounded-lg mb-4"
|
||||||
|
/>
|
||||||
<Select
|
<Select
|
||||||
placeholder={t('请选择该渠道所支持的模型,留空则不更改')}
|
placeholder={t('请选择该渠道所支持的模型,留空则不更改')}
|
||||||
name='models'
|
name='models'
|
||||||
|
|||||||
@@ -219,9 +219,15 @@ const EditToken = (props) => {
|
|||||||
let successCount = 0; // 记录成功创建的令牌数量
|
let successCount = 0; // 记录成功创建的令牌数量
|
||||||
for (let i = 0; i < tokenCount; i++) {
|
for (let i = 0; i < tokenCount; i++) {
|
||||||
let localInputs = { ...inputs };
|
let localInputs = { ...inputs };
|
||||||
if (i !== 0) {
|
|
||||||
// 如果用户想要创建多个令牌,则给每个令牌一个序号后缀
|
// 检查用户是否填写了令牌名称
|
||||||
localInputs.name = `${inputs.name}-${generateRandomSuffix()}`;
|
const baseName = inputs.name.trim() === '' ? 'default' : inputs.name;
|
||||||
|
|
||||||
|
if (i !== 0 || inputs.name.trim() === '') {
|
||||||
|
// 如果创建多个令牌(i !== 0)或者用户没有填写名称,则添加随机后缀
|
||||||
|
localInputs.name = `${baseName}-${generateRandomSuffix()}`;
|
||||||
|
} else {
|
||||||
|
localInputs.name = baseName;
|
||||||
}
|
}
|
||||||
localInputs.remain_quota = parseInt(localInputs.remain_quota);
|
localInputs.remain_quota = parseInt(localInputs.remain_quota);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user