mirror of
				https://github.com/songquanpeng/one-api.git
				synced 2025-11-04 15:53:42 +08:00 
			
		
		
		
	Compare commits
	
		
			35 Commits
		
	
	
		
			v0.6.11-al
			...
			v0.6.11-pr
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					5c81e40612 | ||
| 
						 | 
					0d5318b1b7 | ||
| 
						 | 
					db65db2807 | ||
| 
						 | 
					e0b7e6a9e2 | ||
| 
						 | 
					27c2abe80f | ||
| 
						 | 
					2c867251b5 | ||
| 
						 | 
					108111ebd3 | ||
| 
						 | 
					293ba93ad6 | ||
| 
						 | 
					faced40d5b | ||
| 
						 | 
					2ae9997f29 | ||
| 
						 | 
					e146b14d46 | ||
| 
						 | 
					e19045f925 | ||
| 
						 | 
					d2903b673d | ||
| 
						 | 
					33edcf604c | ||
| 
						 | 
					78fd6ef161 | ||
| 
						 | 
					9b6d5f76e0 | ||
| 
						 | 
					2250f311e1 | ||
| 
						 | 
					e43f758623 | ||
| 
						 | 
					6ded638f70 | ||
| 
						 | 
					ea3331b79a | ||
| 
						 | 
					7a97ddc03c | ||
| 
						 | 
					d7028b55fd | ||
| 
						 | 
					36a03f465b | ||
| 
						 | 
					ae16647047 | ||
| 
						 | 
					4dbc2ad86d | ||
| 
						 | 
					94479c2800 | ||
| 
						 | 
					614903b524 | ||
| 
						 | 
					1dc255c219 | ||
| 
						 | 
					15c27e4b12 | ||
| 
						 | 
					a910d3ba25 | ||
| 
						 | 
					34f889437d | ||
| 
						 | 
					a56cb4a2d5 | ||
| 
						 | 
					95009b254a | ||
| 
						 | 
					20c30a060b | ||
| 
						 | 
					ca334a5502 | 
							
								
								
									
										11
									
								
								.github/workflows/docker-image.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								.github/workflows/docker-image.yml
									
									
									
									
										vendored
									
									
								
							@@ -32,10 +32,10 @@ jobs:
 | 
			
		||||
          git describe --tags > VERSION 
 | 
			
		||||
 | 
			
		||||
      - name: Set up QEMU
 | 
			
		||||
        uses: docker/setup-qemu-action@v2
 | 
			
		||||
        uses: docker/setup-qemu-action@v3
 | 
			
		||||
 | 
			
		||||
      - name: Set up Docker Buildx
 | 
			
		||||
        uses: docker/setup-buildx-action@v2
 | 
			
		||||
        uses: docker/setup-buildx-action@v3
 | 
			
		||||
 | 
			
		||||
      - name: Log in to Docker Hub
 | 
			
		||||
        uses: docker/login-action@v2
 | 
			
		||||
@@ -62,8 +62,9 @@ jobs:
 | 
			
		||||
        uses: docker/build-push-action@v3
 | 
			
		||||
        with:
 | 
			
		||||
          context: .
 | 
			
		||||
          #          platforms: linux/amd64,linux/arm64
 | 
			
		||||
          platforms: linux/amd64 # TODO disable arm64 for now, because it cause error
 | 
			
		||||
          platforms: ${{ contains(github.ref, 'alpha') && 'linux/amd64' || 'linux/amd64,linux/arm64' }}
 | 
			
		||||
          push: true
 | 
			
		||||
          tags: ${{ steps.meta.outputs.tags }}
 | 
			
		||||
          labels: ${{ steps.meta.outputs.labels }}
 | 
			
		||||
          labels: ${{ steps.meta.outputs.labels }}
 | 
			
		||||
          build-args: |
 | 
			
		||||
            TARGETARCH=${{ startsWith(matrix.platform, 'linux/arm64') && 'arm64' || 'amd64' }}
 | 
			
		||||
							
								
								
									
										1
									
								
								.github/workflows/linux-release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/linux-release.yml
									
									
									
									
										vendored
									
									
								
							@@ -7,6 +7,7 @@ on:
 | 
			
		||||
    tags:
 | 
			
		||||
      - 'v*.*.*'
 | 
			
		||||
      - '!*-alpha*'
 | 
			
		||||
      - '!*-preview*'
 | 
			
		||||
  workflow_dispatch:
 | 
			
		||||
    inputs:
 | 
			
		||||
      name:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								.github/workflows/macos-release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/macos-release.yml
									
									
									
									
										vendored
									
									
								
							@@ -7,6 +7,7 @@ on:
 | 
			
		||||
    tags:
 | 
			
		||||
      - 'v*.*.*'
 | 
			
		||||
      - '!*-alpha*'
 | 
			
		||||
      - '!*-preview*'
 | 
			
		||||
  workflow_dispatch:
 | 
			
		||||
    inputs:
 | 
			
		||||
      name:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								.github/workflows/windows-release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/windows-release.yml
									
									
									
									
										vendored
									
									
								
							@@ -7,6 +7,7 @@ on:
 | 
			
		||||
    tags:
 | 
			
		||||
      - 'v*.*.*'
 | 
			
		||||
      - '!*-alpha*'
 | 
			
		||||
      - '!*-preview*'
 | 
			
		||||
  workflow_dispatch:
 | 
			
		||||
    inputs:
 | 
			
		||||
      name:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										29
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								Dockerfile
									
									
									
									
									
								
							@@ -9,23 +9,23 @@ RUN npm install --prefix /web/default & \
 | 
			
		||||
    npm install --prefix /web/air & \
 | 
			
		||||
    wait
 | 
			
		||||
 | 
			
		||||
RUN DISABLE_ESLINT_PLUGIN='true' REACT_APP_VERSION=$(cat /web/default/VERSION) npm run build --prefix /web/default & \
 | 
			
		||||
    DISABLE_ESLINT_PLUGIN='true' REACT_APP_VERSION=$(cat /web/berry/VERSION) npm run build --prefix /web/berry & \
 | 
			
		||||
    DISABLE_ESLINT_PLUGIN='true' REACT_APP_VERSION=$(cat /web/air/VERSION) npm run build --prefix /web/air & \
 | 
			
		||||
RUN DISABLE_ESLINT_PLUGIN='true' REACT_APP_VERSION=$(cat ./VERSION) npm run build --prefix /web/default & \
 | 
			
		||||
    DISABLE_ESLINT_PLUGIN='true' REACT_APP_VERSION=$(cat ./VERSION) npm run build --prefix /web/berry & \
 | 
			
		||||
    DISABLE_ESLINT_PLUGIN='true' REACT_APP_VERSION=$(cat ./VERSION) npm run build --prefix /web/air & \
 | 
			
		||||
    wait
 | 
			
		||||
 | 
			
		||||
FROM golang AS builder2
 | 
			
		||||
FROM golang:alpine AS builder2
 | 
			
		||||
 | 
			
		||||
RUN apt-get update && apt-get install -y --no-install-recommends \
 | 
			
		||||
    build-essential \
 | 
			
		||||
    sqlite3 libsqlite3-dev \
 | 
			
		||||
    && rm -rf /var/lib/apt/lists/*
 | 
			
		||||
RUN apk add --no-cache \
 | 
			
		||||
    gcc \
 | 
			
		||||
    musl-dev \
 | 
			
		||||
    sqlite-dev \
 | 
			
		||||
    build-base
 | 
			
		||||
 | 
			
		||||
ENV GO111MODULE=on \
 | 
			
		||||
    CGO_ENABLED=1 \
 | 
			
		||||
    GOOS=linux \
 | 
			
		||||
    CGO_CFLAGS="-I/usr/include" \
 | 
			
		||||
    CGO_LDFLAGS="-L/usr/lib"
 | 
			
		||||
    GOARCH=$TARGETARCH
 | 
			
		||||
 | 
			
		||||
WORKDIR /build
 | 
			
		||||
 | 
			
		||||
@@ -35,14 +35,11 @@ RUN go mod download
 | 
			
		||||
COPY . .
 | 
			
		||||
COPY --from=builder /web/build ./web/build
 | 
			
		||||
 | 
			
		||||
RUN go build -trimpath -ldflags "-s -w -X 'github.com/songquanpeng/one-api/common.Version=$(cat VERSION)'" -o one-api
 | 
			
		||||
RUN go build -trimpath -ldflags "-s -w -X 'github.com/songquanpeng/one-api/common.Version=$(cat VERSION)' -linkmode external -extldflags '-static'" -o one-api
 | 
			
		||||
 | 
			
		||||
# Final runtime image
 | 
			
		||||
FROM ubuntu:22.04
 | 
			
		||||
FROM alpine:latest
 | 
			
		||||
 | 
			
		||||
RUN apt-get update && apt-get install -y --no-install-recommends \
 | 
			
		||||
    ca-certificates tzdata bash \
 | 
			
		||||
    && rm -rf /var/lib/apt/lists/*
 | 
			
		||||
RUN apk add --no-cache ca-certificates tzdata
 | 
			
		||||
 | 
			
		||||
COPY --from=builder2 /build/one-api /
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -57,10 +57,10 @@ _✨ 通过标准的 OpenAI API 格式访问所有的大模型,开箱即用 
 | 
			
		||||
> 根据[《生成式人工智能服务管理暂行办法》](http://www.cac.gov.cn/2023-07/13/c_1690898327029107.htm)的要求,请勿对中国地区公众提供一切未经备案的生成式人工智能服务。
 | 
			
		||||
 | 
			
		||||
> [!NOTE]
 | 
			
		||||
> 稳定版镜像地址:[justsong/one-api](https://hub.docker.com/repository/docker/justsong/one-api)
 | 
			
		||||
> 稳定版 / 预览版镜像地址:[justsong/one-api](https://hub.docker.com/repository/docker/justsong/one-api)
 | 
			
		||||
> 或者 [ghcr.io/songquanpeng/one-api](https://github.com/songquanpeng/one-api/pkgs/container/one-api)
 | 
			
		||||
>
 | 
			
		||||
> 预览版镜像地址:[justsong/one-api-alpha](https://hub.docker.com/repository/docker/justsong/one-api-alpha)
 | 
			
		||||
> alpha 版镜像地址:[justsong/one-api-alpha](https://hub.docker.com/repository/docker/justsong/one-api-alpha)
 | 
			
		||||
> 或者 [ghcr.io/songquanpeng/one-api-alpha](https://github.com/songquanpeng/one-api/pkgs/container/one-api-alpha)
 | 
			
		||||
 | 
			
		||||
> [!WARNING]
 | 
			
		||||
@@ -93,7 +93,7 @@ _✨ 通过标准的 OpenAI API 格式访问所有的大模型,开箱即用 
 | 
			
		||||
   + [x] [DeepL](https://www.deepl.com/)
 | 
			
		||||
   + [x] [together.ai](https://www.together.ai/)
 | 
			
		||||
   + [x] [novita.ai](https://www.novita.ai/)
 | 
			
		||||
   + [x] [硅基流动 SiliconCloud](https://siliconflow.cn/siliconcloud)
 | 
			
		||||
   + [x] [硅基流动 SiliconCloud](https://cloud.siliconflow.cn/i/rKXmRobW)
 | 
			
		||||
   + [x] [xAI](https://x.ai/)
 | 
			
		||||
2. 支持配置镜像以及众多[第三方代理服务](https://iamazing.cn/page/openai-api-third-party-services)。
 | 
			
		||||
3. 支持通过**负载均衡**的方式访问多个渠道。
 | 
			
		||||
 
 | 
			
		||||
@@ -126,10 +126,10 @@ var ValidThemes = map[string]bool{
 | 
			
		||||
// All duration's unit is seconds
 | 
			
		||||
// Shouldn't larger then RateLimitKeyExpirationDuration
 | 
			
		||||
var (
 | 
			
		||||
	GlobalApiRateLimitNum            = env.Int("GLOBAL_API_RATE_LIMIT", 240)
 | 
			
		||||
	GlobalApiRateLimitNum            = env.Int("GLOBAL_API_RATE_LIMIT", 480)
 | 
			
		||||
	GlobalApiRateLimitDuration int64 = 3 * 60
 | 
			
		||||
 | 
			
		||||
	GlobalWebRateLimitNum            = env.Int("GLOBAL_WEB_RATE_LIMIT", 120)
 | 
			
		||||
	GlobalWebRateLimitNum            = env.Int("GLOBAL_WEB_RATE_LIMIT", 240)
 | 
			
		||||
	GlobalWebRateLimitDuration int64 = 3 * 60
 | 
			
		||||
 | 
			
		||||
	UploadRateLimitNum            = 10
 | 
			
		||||
 
 | 
			
		||||
@@ -3,10 +3,11 @@ package common
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"github.com/gin-gonic/gin"
 | 
			
		||||
	"github.com/songquanpeng/one-api/common/ctxkey"
 | 
			
		||||
	"io"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/gin-gonic/gin"
 | 
			
		||||
	"github.com/songquanpeng/one-api/common/ctxkey"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func GetRequestBody(c *gin.Context) ([]byte, error) {
 | 
			
		||||
@@ -31,7 +32,6 @@ func UnmarshalBodyReusable(c *gin.Context, v any) error {
 | 
			
		||||
	contentType := c.Request.Header.Get("Content-Type")
 | 
			
		||||
	if strings.HasPrefix(contentType, "application/json") {
 | 
			
		||||
		err = json.Unmarshal(requestBody, &v)
 | 
			
		||||
		c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
 | 
			
		||||
	} else {
 | 
			
		||||
		c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
 | 
			
		||||
		err = c.ShouldBind(&v)
 | 
			
		||||
@@ -40,6 +40,7 @@ func UnmarshalBodyReusable(c *gin.Context, v any) error {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	// Reset request body
 | 
			
		||||
	c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -35,6 +35,8 @@ func ShouldDisableChannel(err *model.Error, statusCode int) bool {
 | 
			
		||||
		strings.Contains(lowerMessage, "balance") ||
 | 
			
		||||
		strings.Contains(lowerMessage, "permission denied") ||
 | 
			
		||||
		strings.Contains(lowerMessage, "organization has been restricted") || // groq
 | 
			
		||||
		strings.Contains(lowerMessage, "api key not valid") || // gemini
 | 
			
		||||
		strings.Contains(lowerMessage, "api key expired") || // gemini
 | 
			
		||||
		strings.Contains(lowerMessage, "已欠费") {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ var ModelList = []string{
 | 
			
		||||
	"claude-instant-1.2", "claude-2.0", "claude-2.1",
 | 
			
		||||
	"claude-3-haiku-20240307",
 | 
			
		||||
	"claude-3-5-haiku-20241022",
 | 
			
		||||
	"claude-3-5-haiku-latest",
 | 
			
		||||
	"claude-3-sonnet-20240229",
 | 
			
		||||
	"claude-3-opus-20240229",
 | 
			
		||||
	"claude-3-5-sonnet-20240620",
 | 
			
		||||
 
 | 
			
		||||
@@ -2,5 +2,5 @@ package deepseek
 | 
			
		||||
 | 
			
		||||
var ModelList = []string{
 | 
			
		||||
	"deepseek-chat",
 | 
			
		||||
	"deepseek-coder",
 | 
			
		||||
	"deepseek-reasoner",
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	"github.com/gin-gonic/gin"
 | 
			
		||||
 | 
			
		||||
	"github.com/songquanpeng/one-api/common/helper"
 | 
			
		||||
	channelhelper "github.com/songquanpeng/one-api/relay/adaptor"
 | 
			
		||||
	"github.com/songquanpeng/one-api/relay/adaptor/openai"
 | 
			
		||||
@@ -29,6 +30,8 @@ func (a *Adaptor) GetRequestURL(meta *meta.Meta) (string, error) {
 | 
			
		||||
		"gemini-2.0-flash-thinking-exp",
 | 
			
		||||
		"gemini-2.0-flash-thinking-exp-01-21":
 | 
			
		||||
		defaultVersion = "v1beta"
 | 
			
		||||
	default:
 | 
			
		||||
		defaultVersion = "v1beta"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	version := helper.AssignOrDefault(meta.Config.APIVersion, defaultVersion)
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,6 @@ package groq
 | 
			
		||||
// https://console.groq.com/docs/models
 | 
			
		||||
 | 
			
		||||
var ModelList = []string{
 | 
			
		||||
	"gemma-7b-it",
 | 
			
		||||
	"gemma2-9b-it",
 | 
			
		||||
	"llama-3.1-70b-versatile",
 | 
			
		||||
	"llama-3.1-8b-instant",
 | 
			
		||||
@@ -11,7 +10,6 @@ var ModelList = []string{
 | 
			
		||||
	"llama-3.2-11b-vision-preview",
 | 
			
		||||
	"llama-3.2-1b-preview",
 | 
			
		||||
	"llama-3.2-3b-preview",
 | 
			
		||||
	"llama-3.2-11b-vision-preview",
 | 
			
		||||
	"llama-3.2-90b-text-preview",
 | 
			
		||||
	"llama-3.2-90b-vision-preview",
 | 
			
		||||
	"llama-guard-3-8b",
 | 
			
		||||
@@ -24,4 +22,6 @@ var ModelList = []string{
 | 
			
		||||
	"distil-whisper-large-v3-en",
 | 
			
		||||
	"whisper-large-v3",
 | 
			
		||||
	"whisper-large-v3-turbo",
 | 
			
		||||
	"deepseek-r1-distill-llama-70b-specdec",
 | 
			
		||||
	"deepseek-r1-distill-llama-70b",
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,14 @@
 | 
			
		||||
package zhipu
 | 
			
		||||
 | 
			
		||||
// https://open.bigmodel.cn/pricing
 | 
			
		||||
 | 
			
		||||
var ModelList = []string{
 | 
			
		||||
	"chatglm_turbo", "chatglm_pro", "chatglm_std", "chatglm_lite",
 | 
			
		||||
	"glm-4", "glm-4v", "glm-3-turbo", "embedding-2",
 | 
			
		||||
	"cogview-3",
 | 
			
		||||
	"glm-zero-preview", "glm-4-plus", "glm-4-0520", "glm-4-airx",
 | 
			
		||||
	"glm-4-air", "glm-4-long", "glm-4-flashx", "glm-4-flash",
 | 
			
		||||
	"glm-4", "glm-3-turbo",
 | 
			
		||||
	"glm-4v-plus", "glm-4v", "glm-4v-flash",
 | 
			
		||||
	"cogview-3-plus", "cogview-3", "cogview-3-flash",
 | 
			
		||||
	"cogviewx", "cogviewx-flash",
 | 
			
		||||
	"charglm-4", "emohaa", "codegeex-4",
 | 
			
		||||
	"embedding-2", "embedding-3",
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -82,15 +82,17 @@ var ModelRatio = map[string]float64{
 | 
			
		||||
	"text-moderation-latest":  0.1,
 | 
			
		||||
	"dall-e-2":                0.02 * USD, // $0.016 - $0.020 / image
 | 
			
		||||
	"dall-e-3":                0.04 * USD, // $0.040 - $0.120 / image
 | 
			
		||||
	// https://www.anthropic.com/api#pricing
 | 
			
		||||
	// https://docs.anthropic.com/en/docs/about-claude/models
 | 
			
		||||
	"claude-instant-1.2":         0.8 / 1000 * USD,
 | 
			
		||||
	"claude-2.0":                 8.0 / 1000 * USD,
 | 
			
		||||
	"claude-2.1":                 8.0 / 1000 * USD,
 | 
			
		||||
	"claude-3-haiku-20240307":    0.25 / 1000 * USD,
 | 
			
		||||
	"claude-3-5-haiku-20241022":  1.0 / 1000 * USD,
 | 
			
		||||
	"claude-3-5-haiku-latest":    1.0 / 1000 * USD,	
 | 
			
		||||
	"claude-3-sonnet-20240229":   3.0 / 1000 * USD,
 | 
			
		||||
	"claude-3-5-sonnet-20240620": 3.0 / 1000 * USD,
 | 
			
		||||
	"claude-3-5-sonnet-20241022": 3.0 / 1000 * USD,
 | 
			
		||||
	"claude-3-5-sonnet-latest"  : 3.0 / 1000 * USD,	
 | 
			
		||||
	"claude-3-opus-20240229":     15.0 / 1000 * USD,
 | 
			
		||||
	// https://cloud.baidu.com/doc/WENXINWORKSHOP/s/hlrk4akp7
 | 
			
		||||
	"ERNIE-4.0-8K":       0.120 * RMB,
 | 
			
		||||
@@ -121,15 +123,29 @@ var ModelRatio = map[string]float64{
 | 
			
		||||
	"gemini-2.0-flash-thinking-exp-01-21": 1,
 | 
			
		||||
	"aqa":                                 1,
 | 
			
		||||
	// https://open.bigmodel.cn/pricing
 | 
			
		||||
	"glm-4":         0.1 * RMB,
 | 
			
		||||
	"glm-4v":        0.1 * RMB,
 | 
			
		||||
	"glm-3-turbo":   0.005 * RMB,
 | 
			
		||||
	"embedding-2":   0.0005 * RMB,
 | 
			
		||||
	"chatglm_turbo": 0.3572, // ¥0.005 / 1k tokens
 | 
			
		||||
	"chatglm_pro":   0.7143, // ¥0.01 / 1k tokens
 | 
			
		||||
	"chatglm_std":   0.3572, // ¥0.005 / 1k tokens
 | 
			
		||||
	"chatglm_lite":  0.1429, // ¥0.002 / 1k tokens
 | 
			
		||||
	"cogview-3":     0.25 * RMB,
 | 
			
		||||
	"glm-zero-preview": 0.01 * RMB,
 | 
			
		||||
	"glm-4-plus":       0.05 * RMB,
 | 
			
		||||
	"glm-4-0520":       0.1 * RMB,
 | 
			
		||||
	"glm-4-airx":       0.01 * RMB,
 | 
			
		||||
	"glm-4-air":        0.0005 * RMB,
 | 
			
		||||
	"glm-4-long":       0.001 * RMB,
 | 
			
		||||
	"glm-4-flashx":     0.0001 * RMB,
 | 
			
		||||
	"glm-4-flash":      0,
 | 
			
		||||
	"glm-4":            0.1 * RMB,   // deprecated model, available until 2025/06
 | 
			
		||||
	"glm-3-turbo":      0.001 * RMB, // deprecated model, available until 2025/06
 | 
			
		||||
	"glm-4v-plus":      0.004 * RMB,
 | 
			
		||||
	"glm-4v":           0.05 * RMB,
 | 
			
		||||
	"glm-4v-flash":     0,
 | 
			
		||||
	"cogview-3-plus":   0.06 * RMB,
 | 
			
		||||
	"cogview-3":        0.1 * RMB,
 | 
			
		||||
	"cogview-3-flash":  0,
 | 
			
		||||
	"cogviewx":         0.5 * RMB,
 | 
			
		||||
	"cogviewx-flash":   0,
 | 
			
		||||
	"charglm-4":        0.001 * RMB,
 | 
			
		||||
	"emohaa":           0.015 * RMB,
 | 
			
		||||
	"codegeex-4":       0.0001 * RMB,
 | 
			
		||||
	"embedding-2":      0.0005 * RMB,
 | 
			
		||||
	"embedding-3":      0.0005 * RMB,
 | 
			
		||||
	// https://help.aliyun.com/zh/dashscope/developer-reference/tongyi-thousand-questions-metering-and-billing
 | 
			
		||||
	"qwen-turbo":                  1.4286, // ¥0.02 / 1k tokens
 | 
			
		||||
	"qwen-turbo-latest":           1.4286,
 | 
			
		||||
@@ -216,9 +232,19 @@ var ModelRatio = map[string]float64{
 | 
			
		||||
	"embedding-bert-512-v1":       0.0715, // ¥0.001 / 1k tokens
 | 
			
		||||
	"embedding_s1_v1":             0.0715, // ¥0.001 / 1k tokens
 | 
			
		||||
	"semantic_similarity_s1_v1":   0.0715, // ¥0.001 / 1k tokens
 | 
			
		||||
	"hunyuan":                     7.143,  // ¥0.1 / 1k tokens  // https://cloud.tencent.com/document/product/1729/97731#e0e6be58-60c8-469f-bdeb-6c264ce3b4d0
 | 
			
		||||
	"ChatStd":                     0.01 * RMB,
 | 
			
		||||
	"ChatPro":                     0.1 * RMB,
 | 
			
		||||
	// https://cloud.tencent.com/document/product/1729/97731#e0e6be58-60c8-469f-bdeb-6c264ce3b4d0
 | 
			
		||||
	"hunyuan-turbo":             0.015 * RMB,
 | 
			
		||||
	"hunyuan-large":             0.004 * RMB,
 | 
			
		||||
	"hunyuan-large-longcontext": 0.006 * RMB,
 | 
			
		||||
	"hunyuan-standard":          0.0008 * RMB,
 | 
			
		||||
	"hunyuan-standard-256K":     0.0005 * RMB,
 | 
			
		||||
	"hunyuan-translation-lite":  0.005 * RMB,
 | 
			
		||||
	"hunyuan-role":              0.004 * RMB,
 | 
			
		||||
	"hunyuan-functioncall":      0.004 * RMB,
 | 
			
		||||
	"hunyuan-code":              0.004 * RMB,
 | 
			
		||||
	"hunyuan-turbo-vision":      0.08 * RMB,
 | 
			
		||||
	"hunyuan-vision":            0.018 * RMB,
 | 
			
		||||
	"hunyuan-embedding":         0.0007 * RMB,
 | 
			
		||||
	// https://platform.moonshot.cn/pricing
 | 
			
		||||
	"moonshot-v1-8k":   0.012 * RMB,
 | 
			
		||||
	"moonshot-v1-32k":  0.024 * RMB,
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,6 @@
 | 
			
		||||
    "history": "^5.3.0",
 | 
			
		||||
    "i18next": "^24.2.2",
 | 
			
		||||
    "i18next-browser-languagedetector": "^8.0.2",
 | 
			
		||||
    "i18next-http-backend": "^3.0.2",
 | 
			
		||||
    "marked": "^4.1.1",
 | 
			
		||||
    "moment": "^2.30.1",
 | 
			
		||||
    "react": "^18.2.0",
 | 
			
		||||
 
 | 
			
		||||
@@ -328,6 +328,7 @@ const LogsTable = () => {
 | 
			
		||||
          <Form.Input
 | 
			
		||||
            fluid
 | 
			
		||||
            label={t('log.table.token_name')}
 | 
			
		||||
            size={'small'}
 | 
			
		||||
            width={3}
 | 
			
		||||
            value={token_name}
 | 
			
		||||
            placeholder={t('log.table.token_name_placeholder')}
 | 
			
		||||
@@ -337,6 +338,7 @@ const LogsTable = () => {
 | 
			
		||||
          <Form.Input
 | 
			
		||||
            fluid
 | 
			
		||||
            label={t('log.table.model_name')}
 | 
			
		||||
            size={'small'}
 | 
			
		||||
            width={3}
 | 
			
		||||
            value={model_name}
 | 
			
		||||
            placeholder={t('log.table.model_name_placeholder')}
 | 
			
		||||
@@ -346,6 +348,7 @@ const LogsTable = () => {
 | 
			
		||||
          <Form.Input
 | 
			
		||||
            fluid
 | 
			
		||||
            label={t('log.table.start_time')}
 | 
			
		||||
            size={'small'}
 | 
			
		||||
            width={4}
 | 
			
		||||
            value={start_timestamp}
 | 
			
		||||
            type='datetime-local'
 | 
			
		||||
@@ -355,6 +358,7 @@ const LogsTable = () => {
 | 
			
		||||
          <Form.Input
 | 
			
		||||
            fluid
 | 
			
		||||
            label={t('log.table.end_time')}
 | 
			
		||||
            size={'small'}
 | 
			
		||||
            width={4}
 | 
			
		||||
            value={end_timestamp}
 | 
			
		||||
            type='datetime-local'
 | 
			
		||||
@@ -364,6 +368,7 @@ const LogsTable = () => {
 | 
			
		||||
          <Form.Button
 | 
			
		||||
            fluid
 | 
			
		||||
            label={t('log.buttons.query')}
 | 
			
		||||
            size={'small'}
 | 
			
		||||
            width={2}
 | 
			
		||||
            onClick={refresh}
 | 
			
		||||
          >
 | 
			
		||||
@@ -376,6 +381,7 @@ const LogsTable = () => {
 | 
			
		||||
              <Form.Input
 | 
			
		||||
                fluid
 | 
			
		||||
                label={t('log.table.channel_id')}
 | 
			
		||||
                size={'small'}
 | 
			
		||||
                width={3}
 | 
			
		||||
                value={channel}
 | 
			
		||||
                placeholder={t('log.table.channel_id_placeholder')}
 | 
			
		||||
@@ -385,6 +391,7 @@ const LogsTable = () => {
 | 
			
		||||
              <Form.Input
 | 
			
		||||
                fluid
 | 
			
		||||
                label={t('log.table.username')}
 | 
			
		||||
                size={'small'}
 | 
			
		||||
                width={3}
 | 
			
		||||
                value={username}
 | 
			
		||||
                placeholder={t('log.table.username_placeholder')}
 | 
			
		||||
 
 | 
			
		||||
@@ -415,9 +415,9 @@ const TokensTable = () => {
 | 
			
		||||
                  </Table.Cell>
 | 
			
		||||
                  <Table.Cell>
 | 
			
		||||
                    <div>
 | 
			
		||||
                      <Button.Group color='green' size={'mini'}>
 | 
			
		||||
                      <Button.Group color='green' size={'tiny'}>
 | 
			
		||||
                        <Button
 | 
			
		||||
                          size={'mini'}
 | 
			
		||||
                          size={'tiny'}
 | 
			
		||||
                          positive
 | 
			
		||||
                          onClick={async () => await onCopy('', token.key)}
 | 
			
		||||
                        >
 | 
			
		||||
@@ -430,9 +430,9 @@ const TokensTable = () => {
 | 
			
		||||
                          trigger={<></>}
 | 
			
		||||
                        />
 | 
			
		||||
                      </Button.Group>{' '}
 | 
			
		||||
                      <Button.Group color='blue' size={'mini'}>
 | 
			
		||||
                      <Button.Group color='olive' size={'tiny'}>
 | 
			
		||||
                        <Button
 | 
			
		||||
                          size={'mini'}
 | 
			
		||||
                          size={'tiny'}
 | 
			
		||||
                          positive
 | 
			
		||||
                          onClick={() => onOpenLink('', token.key)}
 | 
			
		||||
                        >
 | 
			
		||||
@@ -456,7 +456,7 @@ const TokensTable = () => {
 | 
			
		||||
                        hoverable
 | 
			
		||||
                      >
 | 
			
		||||
                        <Button
 | 
			
		||||
                          size={'mini'}
 | 
			
		||||
                          size={'tiny'}
 | 
			
		||||
                          negative
 | 
			
		||||
                          onClick={() => {
 | 
			
		||||
                            manageToken(token.id, 'delete', idx);
 | 
			
		||||
@@ -466,7 +466,7 @@ const TokensTable = () => {
 | 
			
		||||
                        </Button>
 | 
			
		||||
                      </Popup>
 | 
			
		||||
                      <Button
 | 
			
		||||
                        size={'mini'}
 | 
			
		||||
                        size={'tiny'}
 | 
			
		||||
                        onClick={() => {
 | 
			
		||||
                          manageToken(
 | 
			
		||||
                            token.id,
 | 
			
		||||
@@ -480,7 +480,7 @@ const TokensTable = () => {
 | 
			
		||||
                          : t('token.buttons.enable')}
 | 
			
		||||
                      </Button>
 | 
			
		||||
                      <Button
 | 
			
		||||
                        size={'mini'}
 | 
			
		||||
                        size={'tiny'}
 | 
			
		||||
                        as={Link}
 | 
			
		||||
                        to={'/token/edit/' + token.id}
 | 
			
		||||
                      >
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
export const toastConstants = {
 | 
			
		||||
  SUCCESS_TIMEOUT: 1500,
 | 
			
		||||
  INFO_TIMEOUT: 3000,
 | 
			
		||||
  ERROR_TIMEOUT: 5000,
 | 
			
		||||
  SUCCESS_TIMEOUT: 5000,
 | 
			
		||||
  INFO_TIMEOUT: 8000,
 | 
			
		||||
  ERROR_TIMEOUT: 10000,
 | 
			
		||||
  WARNING_TIMEOUT: 10000,
 | 
			
		||||
  NOTICE_TIMEOUT: 20000
 | 
			
		||||
  NOTICE_TIMEOUT: 20000,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,10 @@
 | 
			
		||||
import i18n from 'i18next';
 | 
			
		||||
import { initReactI18next } from 'react-i18next';
 | 
			
		||||
import Backend from 'i18next-http-backend';
 | 
			
		||||
import {initReactI18next} from 'react-i18next';
 | 
			
		||||
import LanguageDetector from 'i18next-browser-languagedetector';
 | 
			
		||||
import zhTranslation from './locales/zh/translation.json';
 | 
			
		||||
import enTranslation from './locales/en/translation.json';
 | 
			
		||||
 | 
			
		||||
i18n
 | 
			
		||||
  .use(Backend)
 | 
			
		||||
  .use(LanguageDetector)
 | 
			
		||||
  .use(initReactI18next)
 | 
			
		||||
  .init({
 | 
			
		||||
@@ -15,9 +15,14 @@ i18n
 | 
			
		||||
      escapeValue: false,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    backend: {
 | 
			
		||||
      loadPath: '/locales/{{lng}}/{{ns}}.json',
 | 
			
		||||
    },
 | 
			
		||||
      resources: {
 | 
			
		||||
          zh: {
 | 
			
		||||
              translation: zhTranslation
 | 
			
		||||
          },
 | 
			
		||||
          en: {
 | 
			
		||||
              translation: enTranslation
 | 
			
		||||
          }
 | 
			
		||||
      }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
export default i18n;
 | 
			
		||||
 
 | 
			
		||||
@@ -62,7 +62,8 @@
 | 
			
		||||
      "not_tested": "Not Tested",
 | 
			
		||||
      "priority_tip": "Channel selection priority, higher is preferred",
 | 
			
		||||
      "select_test_model": "Please select test model",
 | 
			
		||||
      "click_to_update": "Click to update"
 | 
			
		||||
      "click_to_update": "Click to update",
 | 
			
		||||
      "balance_not_supported": "-"
 | 
			
		||||
    },
 | 
			
		||||
    "buttons": {
 | 
			
		||||
      "test": "Test",
 | 
			
		||||
@@ -85,7 +86,8 @@
 | 
			
		||||
      "test_all_started": "Channel testing started successfully, please refresh page to see results.",
 | 
			
		||||
      "delete_disabled_success": "Deleted all disabled channels, total: {{count}}",
 | 
			
		||||
      "balance_update_success": "Channel {{name}} balance updated successfully!",
 | 
			
		||||
      "all_balance_updated": "All enabled channel balances have been updated!"
 | 
			
		||||
      "all_balance_updated": "All enabled channel balances have been updated!",
 | 
			
		||||
      "operation_success": "Operation completed successfully!"
 | 
			
		||||
    },
 | 
			
		||||
    "edit": {
 | 
			
		||||
      "title_edit": "Update Channel Information",
 | 
			
		||||
@@ -165,7 +167,7 @@
 | 
			
		||||
      "expired_time": "Expiry Time",
 | 
			
		||||
      "actions": "Actions",
 | 
			
		||||
      "no_name": "None",
 | 
			
		||||
      "never_expire": "Never Expires",
 | 
			
		||||
      "never_expire": "never",
 | 
			
		||||
      "unlimited": "Unlimited",
 | 
			
		||||
      "status_enabled": "Enabled",
 | 
			
		||||
      "status_disabled": "Disabled",
 | 
			
		||||
@@ -62,7 +62,8 @@
 | 
			
		||||
      "not_tested": "未测试",
 | 
			
		||||
      "priority_tip": "渠道选择优先级,越高越优先",
 | 
			
		||||
      "select_test_model": "请选择测试模型",
 | 
			
		||||
      "click_to_update": "点击更新"
 | 
			
		||||
      "click_to_update": "点击更新",
 | 
			
		||||
      "balance_not_supported": "-"
 | 
			
		||||
    },
 | 
			
		||||
    "buttons": {
 | 
			
		||||
      "test": "测试",
 | 
			
		||||
@@ -85,7 +86,8 @@
 | 
			
		||||
      "test_all_started": "已成功开始测试渠道,请刷新页面查看结果。",
 | 
			
		||||
      "delete_disabled_success": "已删除所有禁用渠道,共计 {{count}} 个",
 | 
			
		||||
      "balance_update_success": "渠道 {{name}} 余额更新成功!",
 | 
			
		||||
      "all_balance_updated": "已更新完毕所有已启用渠道余额!"
 | 
			
		||||
      "all_balance_updated": "已更新完毕所有已启用渠道余额!",
 | 
			
		||||
      "operation_success": "操作成功完成!"
 | 
			
		||||
    },
 | 
			
		||||
    "edit": {
 | 
			
		||||
      "title_edit": "更新渠道信息",
 | 
			
		||||
@@ -133,7 +135,7 @@
 | 
			
		||||
      "coze_notice": "对于 Coze 而言,模型名称即 Bot ID,你可以添加一个前缀 `bot-`,例如:`bot-123456`。",
 | 
			
		||||
      "douban_notice": "对于豆包而言,需要手动去",
 | 
			
		||||
      "douban_notice_link": "模型推理页面",
 | 
			
		||||
      "douban_notice_2": "创建推理接入点,以接入点名称作为模型名称,例如:`ep-20240608051426-tkxvl`。",
 | 
			
		||||
      "douban_notice_2": "创建推理接入点,以接入点名称作为模型名称,例如:`ep-20240608051426-tkxvl`。你可以结合模型重定向功能将其转换为常规的模型名称,例如:doubao-lite-4k -> ep-20240608051426-tkxvl(前者作为 JSON 的 key,后者作为 value)。注意,doubao-lite-4k 和 ep-20240608051426-tkxvl 都需要通过自定义模型的方式填入到本渠道的模型列表中。",
 | 
			
		||||
      "aws_region_placeholder": "region,例如:us-west-2",
 | 
			
		||||
      "aws_ak_placeholder": "AWS IAM Access Key",
 | 
			
		||||
      "aws_sk_placeholder": "AWS IAM Secret Key",
 | 
			
		||||
@@ -54,10 +54,16 @@ const About = () => {
 | 
			
		||||
              style={{ width: '100%', height: '100vh', border: 'none' }}
 | 
			
		||||
            />
 | 
			
		||||
          ) : (
 | 
			
		||||
            <div
 | 
			
		||||
              style={{ fontSize: 'larger' }}
 | 
			
		||||
              dangerouslySetInnerHTML={{ __html: about }}
 | 
			
		||||
            ></div>
 | 
			
		||||
            <div className='dashboard-container'>
 | 
			
		||||
              <Card fluid className='chart-card'>
 | 
			
		||||
                <Card.Content>
 | 
			
		||||
                  <div
 | 
			
		||||
                    style={{ fontSize: 'larger' }}
 | 
			
		||||
                    dangerouslySetInnerHTML={{ __html: about }}
 | 
			
		||||
                  ></div>
 | 
			
		||||
                </Card.Content>
 | 
			
		||||
              </Card>
 | 
			
		||||
            </div>
 | 
			
		||||
          )}
 | 
			
		||||
        </>
 | 
			
		||||
      )}
 | 
			
		||||
 
 | 
			
		||||
@@ -207,6 +207,9 @@ const EditChannel = () => {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    let localInputs = { ...inputs };
 | 
			
		||||
    if (localInputs.key === 'undefined|undefined|undefined') {
 | 
			
		||||
      localInputs.key = ''; // prevent potential bug
 | 
			
		||||
    }
 | 
			
		||||
    if (localInputs.base_url && localInputs.base_url.endsWith('/')) {
 | 
			
		||||
      localInputs.base_url = localInputs.base_url.slice(
 | 
			
		||||
        0,
 | 
			
		||||
@@ -622,6 +625,21 @@ const EditChannel = () => {
 | 
			
		||||
                  />
 | 
			
		||||
                </Form.Field>
 | 
			
		||||
              ))}
 | 
			
		||||
            {inputs.type === 37 && (
 | 
			
		||||
              <Form.Field>
 | 
			
		||||
                <Form.Input
 | 
			
		||||
                  label='Account ID'
 | 
			
		||||
                  name='user_id'
 | 
			
		||||
                  required
 | 
			
		||||
                  placeholder={
 | 
			
		||||
                    '请输入 Account ID,例如:d8d7c61dbc334c32d3ced580e4bf42b4'
 | 
			
		||||
                  }
 | 
			
		||||
                  onChange={handleConfigChange}
 | 
			
		||||
                  value={config.user_id}
 | 
			
		||||
                  autoComplete=''
 | 
			
		||||
                />
 | 
			
		||||
              </Form.Field>
 | 
			
		||||
            )}
 | 
			
		||||
            {inputs.type !== 33 && !isEdit && (
 | 
			
		||||
              <Form.Checkbox
 | 
			
		||||
                checked={batch}
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,7 @@
 | 
			
		||||
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04) !important;
 | 
			
		||||
    border: none !important;
 | 
			
		||||
    border-radius: 16px !important;
 | 
			
		||||
    padding-top: 8px!important;
 | 
			
		||||
    padding: 8px!important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chart-container {
 | 
			
		||||
@@ -91,15 +91,15 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.settings-tab .item {
 | 
			
		||||
    color: #2B3674 !important;
 | 
			
		||||
    color: #000 !important;
 | 
			
		||||
    font-weight: 500 !important;
 | 
			
		||||
    padding: 0.8rem 1.2rem !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.settings-tab .active.item {
 | 
			
		||||
    color: #4318FF !important;
 | 
			
		||||
    color: #000 !important;
 | 
			
		||||
    font-weight: 600 !important;
 | 
			
		||||
    border-color: #4318FF !important;
 | 
			
		||||
    border-color: #000 !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.ui.tab.segment {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,17 @@
 | 
			
		||||
import React, { useEffect, useState } from 'react';
 | 
			
		||||
import { useTranslation } from 'react-i18next';
 | 
			
		||||
import { Card, Grid, Header, Segment, Statistic } from 'semantic-ui-react';
 | 
			
		||||
import { API, showError } from '../../helpers';
 | 
			
		||||
import moment from 'moment';
 | 
			
		||||
import { Card, Grid } from 'semantic-ui-react';
 | 
			
		||||
import {
 | 
			
		||||
  LineChart,
 | 
			
		||||
  Bar,
 | 
			
		||||
  BarChart,
 | 
			
		||||
  CartesianGrid,
 | 
			
		||||
  Legend,
 | 
			
		||||
  Line,
 | 
			
		||||
  LineChart,
 | 
			
		||||
  ResponsiveContainer,
 | 
			
		||||
  Tooltip,
 | 
			
		||||
  XAxis,
 | 
			
		||||
  YAxis,
 | 
			
		||||
  CartesianGrid,
 | 
			
		||||
  Tooltip,
 | 
			
		||||
  ResponsiveContainer,
 | 
			
		||||
  BarChart,
 | 
			
		||||
  Bar,
 | 
			
		||||
  Legend,
 | 
			
		||||
} from 'recharts';
 | 
			
		||||
import axios from 'axios';
 | 
			
		||||
import './Dashboard.css';
 | 
			
		||||
@@ -244,7 +242,7 @@ const Dashboard = () => {
 | 
			
		||||
            <Card.Content>
 | 
			
		||||
              <Card.Header>
 | 
			
		||||
                {t('dashboard.charts.requests.title')}
 | 
			
		||||
                <span className='stat-value'>{summaryData.todayRequests}</span>
 | 
			
		||||
                {/* <span className='stat-value'>{summaryData.todayRequests}</span> */}
 | 
			
		||||
              </Card.Header>
 | 
			
		||||
              <div className='chart-container'>
 | 
			
		||||
                <ResponsiveContainer
 | 
			
		||||
@@ -273,7 +271,9 @@ const Dashboard = () => {
 | 
			
		||||
                        t('dashboard.charts.requests.tooltip'),
 | 
			
		||||
                      ]}
 | 
			
		||||
                      labelFormatter={(label) =>
 | 
			
		||||
                        `${t('dashboard.tooltip.date')}: ${formatDate(label)}`
 | 
			
		||||
                        `${t(
 | 
			
		||||
                          'dashboard.statistics.tooltip.date'
 | 
			
		||||
                        )}: ${formatDate(label)}`
 | 
			
		||||
                      }
 | 
			
		||||
                    />
 | 
			
		||||
                    <Line
 | 
			
		||||
@@ -296,9 +296,9 @@ const Dashboard = () => {
 | 
			
		||||
            <Card.Content>
 | 
			
		||||
              <Card.Header>
 | 
			
		||||
                {t('dashboard.charts.quota.title')}
 | 
			
		||||
                <span className='stat-value'>
 | 
			
		||||
                {/* <span className='stat-value'>
 | 
			
		||||
                  ${summaryData.todayQuota.toFixed(3)}
 | 
			
		||||
                </span>
 | 
			
		||||
                </span> */}
 | 
			
		||||
              </Card.Header>
 | 
			
		||||
              <div className='chart-container'>
 | 
			
		||||
                <ResponsiveContainer
 | 
			
		||||
@@ -323,11 +323,13 @@ const Dashboard = () => {
 | 
			
		||||
                        boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
 | 
			
		||||
                      }}
 | 
			
		||||
                      formatter={(value) => [
 | 
			
		||||
                        value,
 | 
			
		||||
                        value.toFixed(6),
 | 
			
		||||
                        t('dashboard.charts.quota.tooltip'),
 | 
			
		||||
                      ]}
 | 
			
		||||
                      labelFormatter={(label) =>
 | 
			
		||||
                        `${t('dashboard.tooltip.date')}: ${formatDate(label)}`
 | 
			
		||||
                        `${t(
 | 
			
		||||
                          'dashboard.statistics.tooltip.date'
 | 
			
		||||
                        )}: ${formatDate(label)}`
 | 
			
		||||
                      }
 | 
			
		||||
                    />
 | 
			
		||||
                    <Line
 | 
			
		||||
@@ -350,7 +352,7 @@ const Dashboard = () => {
 | 
			
		||||
            <Card.Content>
 | 
			
		||||
              <Card.Header>
 | 
			
		||||
                {t('dashboard.charts.tokens.title')}
 | 
			
		||||
                <span className='stat-value'>{summaryData.todayTokens}</span>
 | 
			
		||||
                {/* <span className='stat-value'>{summaryData.todayTokens}</span> */}
 | 
			
		||||
              </Card.Header>
 | 
			
		||||
              <div className='chart-container'>
 | 
			
		||||
                <ResponsiveContainer
 | 
			
		||||
@@ -379,7 +381,9 @@ const Dashboard = () => {
 | 
			
		||||
                        t('dashboard.charts.tokens.tooltip'),
 | 
			
		||||
                      ]}
 | 
			
		||||
                      labelFormatter={(label) =>
 | 
			
		||||
                        `${t('dashboard.tooltip.date')}: ${formatDate(label)}`
 | 
			
		||||
                        `${t(
 | 
			
		||||
                          'dashboard.statistics.tooltip.date'
 | 
			
		||||
                        )}: ${formatDate(label)}`
 | 
			
		||||
                      }
 | 
			
		||||
                    />
 | 
			
		||||
                    <Line
 | 
			
		||||
@@ -424,7 +428,9 @@ const Dashboard = () => {
 | 
			
		||||
                    boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
 | 
			
		||||
                  }}
 | 
			
		||||
                  labelFormatter={(label) =>
 | 
			
		||||
                    `${t('dashboard.tooltip.date')}: ${formatDate(label)}`
 | 
			
		||||
                    `${t('dashboard.statistics.tooltip.date')}: ${formatDate(
 | 
			
		||||
                      label
 | 
			
		||||
                    )}`
 | 
			
		||||
                  }
 | 
			
		||||
                />
 | 
			
		||||
                <Legend
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user