Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 762d2c81f5 | |||
| f115342784 | |||
| 58f235af5e | |||
| b197dfb95d | |||
| e0ff3b6f28 | |||
| 5040235919 | |||
| 07f141e8c8 | |||
| e1039c67f7 | |||
| 594636bace | |||
| e647163969 | |||
| c3a205e792 | |||
| e7289297e2 | |||
| 2e04d28483 | |||
| 4069b3f789 | |||
| 2cb067f485 | |||
| 550c068994 | |||
| 8b55c9b917 | |||
| e09931558e | |||
| 18f82f120c | |||
| c4f664f376 | |||
| 28a2387dff | |||
| 098c1e8829 | |||
| 15607996e6 |
@@ -1,54 +0,0 @@
|
||||
name: Publish Docker image (amd64)
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
name:
|
||||
description: 'reason'
|
||||
required: false
|
||||
jobs:
|
||||
push_to_registries:
|
||||
name: Push Docker image to multiple registries
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Save version info
|
||||
run: |
|
||||
git describe --tags > VERSION
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
calciumion/new-api
|
||||
ghcr.io/${{ github.repository }}
|
||||
|
||||
- name: Build and push Docker images
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
@@ -1,14 +1,9 @@
|
||||
name: Publish Docker image (arm64)
|
||||
name: Publish Docker image (Multi Registries)
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
name:
|
||||
description: 'reason'
|
||||
required: false
|
||||
jobs:
|
||||
push_to_registries:
|
||||
name: Push Docker image to multiple registries
|
||||
|
||||
@@ -3,6 +3,11 @@ permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
name:
|
||||
description: 'reason'
|
||||
required: false
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
@@ -15,16 +20,16 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
node-version: 18
|
||||
bun-version: latest
|
||||
- name: Build Frontend
|
||||
env:
|
||||
CI: ""
|
||||
run: |
|
||||
cd web
|
||||
npm install
|
||||
REACT_APP_VERSION=$(git describe --tags) npm run build
|
||||
bun install
|
||||
DISABLE_ESLINT_PLUGIN='true' VITE_REACT_APP_VERSION=$(git describe --tags) bun run build
|
||||
cd ..
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
|
||||
@@ -3,6 +3,11 @@ permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
name:
|
||||
description: 'reason'
|
||||
required: false
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
@@ -15,16 +20,16 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
node-version: 18
|
||||
bun-version: latest
|
||||
- name: Build Frontend
|
||||
env:
|
||||
CI: ""
|
||||
run: |
|
||||
cd web
|
||||
npm install
|
||||
REACT_APP_VERSION=$(git describe --tags) npm run build
|
||||
bun install
|
||||
DISABLE_ESLINT_PLUGIN='true' VITE_REACT_APP_VERSION=$(git describe --tags) bun run build
|
||||
cd ..
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
|
||||
@@ -3,6 +3,11 @@ permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
name:
|
||||
description: 'reason'
|
||||
required: false
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
@@ -18,16 +23,16 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
node-version: 18
|
||||
bun-version: latest
|
||||
- name: Build Frontend
|
||||
env:
|
||||
CI: ""
|
||||
run: |
|
||||
cd web
|
||||
npm install
|
||||
REACT_APP_VERSION=$(git describe --tags) npm run build
|
||||
bun install
|
||||
DISABLE_ESLINT_PLUGIN='true' VITE_REACT_APP_VERSION=$(git describe --tags) bun run build
|
||||
cd ..
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
|
||||
+3
-3
@@ -92,12 +92,12 @@ func RedisDel(key string) error {
|
||||
return RDB.Del(ctx, key).Err()
|
||||
}
|
||||
|
||||
func RedisHDelObj(key string) error {
|
||||
func RedisDelKey(key string) error {
|
||||
if DebugEnabled {
|
||||
SysLog(fmt.Sprintf("Redis HDEL: key=%s", key))
|
||||
SysLog(fmt.Sprintf("Redis DEL Key: key=%s", key))
|
||||
}
|
||||
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 {
|
||||
|
||||
@@ -623,3 +623,44 @@ func BatchSetChannelTag(c *gin.Context) {
|
||||
})
|
||||
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 {
|
||||
key = common.GenerateHMAC(key)
|
||||
err := common.RedisHDelObj(fmt.Sprintf("token:%s", key))
|
||||
err := common.RedisDelKey(fmt.Sprintf("token:%s", key))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+3
-2
@@ -3,11 +3,12 @@ package model
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"one-api/common"
|
||||
"one-api/constant"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/bytedance/gopkg/util/gopool"
|
||||
)
|
||||
|
||||
@@ -57,7 +58,7 @@ func invalidateUserCache(userId int) error {
|
||||
if !common.RedisEnabled {
|
||||
return nil
|
||||
}
|
||||
return common.RedisHDelObj(getUserCacheKey(userId))
|
||||
return common.RedisDelKey(getUserCacheKey(userId))
|
||||
}
|
||||
|
||||
// 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.POST("/fetch_models", controller.FetchModels)
|
||||
channelRoute.POST("/batch/tag", controller.BatchSetChannelTag)
|
||||
channelRoute.GET("/tag/models", controller.GetTagModels)
|
||||
}
|
||||
tokenRoute := apiRouter.Group("/token")
|
||||
tokenRoute.Use(middleware.UserAuth())
|
||||
|
||||
Binary file not shown.
+2
-2
@@ -39,7 +39,7 @@
|
||||
"remark-math": "^6.0.0",
|
||||
"semantic-ui-offline": "^2.5.0",
|
||||
"semantic-ui-react": "^2.1.3",
|
||||
"sse": "https://github.com/mpetazzoni/sse.js",
|
||||
"sse.js": "^2.6.0",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
"use-debounce": "^10.0.4"
|
||||
},
|
||||
@@ -69,7 +69,7 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@douyinfe/semi-webpack-plugin": "^2.78.0",
|
||||
"@douyinfe/vite-plugin-semi": "^2.74.0-alpha.6",
|
||||
"@so1ve/prettier-config": "^3.1.0",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"autoprefixer": "^10.4.21",
|
||||
|
||||
@@ -462,7 +462,7 @@ const LogsTable = () => {
|
||||
percent={text ? parseInt(text.replace('%', '')) : 0}
|
||||
showInfo={true}
|
||||
aria-label='drawing progress'
|
||||
style={{ minWidth: '200px' }}
|
||||
style={{ minWidth: '160px' }}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
@@ -483,6 +483,7 @@ const LogsTable = () => {
|
||||
setModalImageUrl(text);
|
||||
setIsModalOpenurl(true);
|
||||
}}
|
||||
className="!rounded-full"
|
||||
>
|
||||
{t('查看图片')}
|
||||
</Button>
|
||||
|
||||
@@ -395,7 +395,7 @@ const LogsTable = () => {
|
||||
percent={text ? parseInt(text.replace('%', '')) : 0}
|
||||
showInfo={true}
|
||||
aria-label='task progress'
|
||||
style={{ minWidth: '200px' }}
|
||||
style={{ minWidth: '160px' }}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { SSE } from 'sse';
|
||||
import { SSE } from 'sse.js';
|
||||
import {
|
||||
API_ENDPOINTS,
|
||||
MESSAGE_STATUS,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import '@douyinfe/semi-ui/dist/css/semi.css';
|
||||
import { UserProvider } from './context/User';
|
||||
import 'react-toastify/dist/ReactToastify.css';
|
||||
import { StatusProvider } from './context/Status';
|
||||
|
||||
@@ -194,6 +194,24 @@ const EditTagModal = (props) => {
|
||||
}, [originModelOptions, inputs.models]);
|
||||
|
||||
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({
|
||||
...originInputs,
|
||||
tag: tag,
|
||||
@@ -201,7 +219,8 @@ const EditTagModal = (props) => {
|
||||
});
|
||||
fetchModels().then();
|
||||
fetchGroups().then();
|
||||
}, [visible]);
|
||||
fetchTagModels().then(); // Call the new function
|
||||
}, [visible, tag]); // Add tag to dependency array
|
||||
|
||||
const addCustomModels = () => {
|
||||
if (customModel.trim() === '') return;
|
||||
@@ -347,6 +366,11 @@ const EditTagModal = (props) => {
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<Text strong className="block mb-2">{t('模型')}</Text>
|
||||
<Banner
|
||||
type="info"
|
||||
description={t('当前模型列表为该标签下所有渠道模型列表最长的一个,并非所有渠道的并集,请注意可能导致某些渠道模型丢失。')}
|
||||
className="!rounded-lg mb-4"
|
||||
/>
|
||||
<Select
|
||||
placeholder={t('请选择该渠道所支持的模型,留空则不更改')}
|
||||
name='models'
|
||||
|
||||
@@ -219,9 +219,15 @@ const EditToken = (props) => {
|
||||
let successCount = 0; // 记录成功创建的令牌数量
|
||||
for (let i = 0; i < tokenCount; i++) {
|
||||
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);
|
||||
|
||||
|
||||
+5
-11
@@ -1,6 +1,7 @@
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { defineConfig, transformWithEsbuild } from 'vite';
|
||||
import semiWebpackPlugin from '@douyinfe/semi-webpack-plugin';
|
||||
import pkg from '@douyinfe/vite-plugin-semi';
|
||||
const { vitePluginSemi } = pkg;
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
@@ -21,16 +22,9 @@ export default defineConfig({
|
||||
},
|
||||
},
|
||||
react(),
|
||||
{
|
||||
name: 'semi-plugin',
|
||||
apply: 'build',
|
||||
configResolved() {
|
||||
// Apply SemiWebpackPlugin during build
|
||||
new semiWebpackPlugin({
|
||||
cssLayer: true
|
||||
});
|
||||
}
|
||||
}
|
||||
vitePluginSemi({
|
||||
cssLayer: true
|
||||
})
|
||||
],
|
||||
optimizeDeps: {
|
||||
force: true,
|
||||
|
||||
Reference in New Issue
Block a user