-
+ {isYike ? : }
{t('Current Balance')}
diff --git a/web/src/features/channels/components/drawers/channel-mutate-drawer.tsx b/web/src/features/channels/components/drawers/channel-mutate-drawer.tsx
index 3380d9e52c2..99982b82690 100644
--- a/web/src/features/channels/components/drawers/channel-mutate-drawer.tsx
+++ b/web/src/features/channels/components/drawers/channel-mutate-drawer.tsx
@@ -139,12 +139,14 @@ import {
import {
ADD_MODE_OPTIONS,
CHANNEL_STATUS_LABELS,
+ CHANNEL_TYPE_YIKE,
CHANNEL_TYPE_OPTIONS,
CHANNEL_TYPE_WARNINGS,
ERROR_MESSAGES,
FIELD_DESCRIPTIONS,
FIELD_PLACEHOLDERS,
MODEL_FETCHABLE_TYPES,
+ YIKE_KEY_INPUT_GUIDES,
} from '../../constants'
import { useChannelMutateForm } from '../../hooks/use-channel-mutate-form'
import {
@@ -852,6 +854,14 @@ export function ChannelMutateDrawer({
// Helper computed values
const isBatchMode =
multiKeyMode === 'batch' || multiKeyMode === 'multi_to_single'
+ const yikeKeyGuide =
+ currentType === CHANNEL_TYPE_YIKE
+ ? YIKE_KEY_INPUT_GUIDES[
+ isEditing && isMultiKeyChannel
+ ? 'multi_to_single'
+ : (multiKeyMode ?? 'single')
+ ]
+ : undefined
const isChannelDetailLoading = isEditing && isChannelLoading
const supportsMultiKeyAddMode =
currentType !== 57 && !(currentType === 41 && vertexKeyType === 'api_key')
@@ -2923,6 +2933,8 @@ export function ChannelMutateDrawer({
keyPlaceholder = t(
'Leave empty to keep existing key'
)
+ } else if (yikeKeyGuide) {
+ keyPlaceholder = yikeKeyGuide.placeholder
} else if (
currentType === 33 &&
awsKeyType === 'api_key' &&
@@ -2972,6 +2984,11 @@ export function ChannelMutateDrawer({
{t(
'Enter new key to update, or leave empty to keep current key'
)}
+ {yikeKeyGuide && (
+
+ {t(yikeKeyGuide.description)}
+
+ )}
{isMultiKeyChannel && (
{keyModeDescription}
@@ -2979,6 +2996,8 @@ export function ChannelMutateDrawer({
)}
>
)
+ } else if (yikeKeyGuide) {
+ keyDescription = t(yikeKeyGuide.description)
} else if (isBatchMode) {
keyDescription = t(
'Enter one API key per line for batch creation'
diff --git a/web/src/features/channels/constants.ts b/web/src/features/channels/constants.ts
index a3cb726d541..2c994113fcf 100644
--- a/web/src/features/channels/constants.ts
+++ b/web/src/features/channels/constants.ts
@@ -22,6 +22,11 @@ For commercial licensing, please contact support@quantumnous.com
// ============================================================================
export const CHANNEL_TYPE_NEW_API = 60
+export const CHANNEL_TYPE_YIKE = 61
+
+const YIKE_KEY_PAIR_PLACEHOLDER = 'AccessKeyId|AccessKeySecret'
+const YIKE_MULTI_KEY_PLACEHOLDER =
+ 'AccessKeyId_1|AccessKeySecret_1\nAccessKeyId_2|AccessKeySecret_2'
export const CHANNEL_TYPES = {
0: 'Unknown',
@@ -81,12 +86,13 @@ export const CHANNEL_TYPES = {
58: 'Advanced Custom',
59: 'Sub2API',
60: 'New API',
+ [CHANNEL_TYPE_YIKE]: 'Yike',
} as const
const CHANNEL_TYPE_DISPLAY_ORDER: number[] = [
1, 14, 33, 24, 43, 3, 41, 48, 60, 58, 42, 34, 20, 4, 40, 27, 25, 17, 26, 15,
46, 23, 18, 45, 31, 35, 49, 19, 47, 37, 38, 39, 11, 8, 57, 59, 22, 21, 44, 2,
- 5, 36, 50, 51, 52, 53, 54, 55, 56,
+ 5, 36, 50, 51, 52, 61, 53, 54, 55, 56,
]
export const CHANNEL_TYPE_OPTIONS: { value: number; label: string }[] = (() => {
@@ -200,6 +206,24 @@ export const ADD_MODE_OPTIONS = [
},
] as const
+export const YIKE_KEY_INPUT_GUIDES = {
+ single: {
+ placeholder: YIKE_KEY_PAIR_PLACEHOLDER,
+ description:
+ 'Enter one complete credential pair in the format AccessKeyId|AccessKeySecret. Use a half-width vertical bar (|) with no spaces. This channel can query its credits independently.',
+ },
+ batch: {
+ placeholder: YIKE_MULTI_KEY_PLACEHOLDER,
+ description:
+ 'Enter one complete AccessKeyId|AccessKeySecret pair per line. A separate channel is created for each line, and each channel can query its own credits. Do not put the ID and secret on separate lines.',
+ },
+ multi_to_single: {
+ placeholder: YIKE_MULTI_KEY_PLACEHOLDER,
+ description:
+ 'Enter one complete AccessKeyId|AccessKeySecret pair per line. All pairs are stored in one channel and selected randomly or by polling. This mode is for request rotation and does not support querying or summing credits.',
+ },
+} as const
+
// ============================================================================
// Multi-Key Management
// ============================================================================
@@ -389,7 +413,7 @@ export const FIELD_DESCRIPTIONS = {
export const MODEL_FETCHABLE_TYPES = new Set([
1, 4, 14, 17, 20, 23, 24, 25, 26, 27, 31, 34, 35, 40, 42, 43, 47, 48, 57, 58,
- 59, 60,
+ 59, 60, 61,
])
export const TYPE_TO_KEY_PROMPT: Record = {
@@ -403,6 +427,7 @@ export const TYPE_TO_KEY_PROMPT: Record = {
57: 'Paste Codex OAuth JSON credential (access_token / refresh_token / account_id)',
59: 'Enter API key for this channel',
60: 'Enter API key for this channel',
+ [CHANNEL_TYPE_YIKE]: YIKE_KEY_PAIR_PLACEHOLDER,
}
export const CHANNEL_TYPE_WARNINGS: Record = {
diff --git a/web/src/features/channels/lib/__tests__/yike-balance.test.ts b/web/src/features/channels/lib/__tests__/yike-balance.test.ts
new file mode 100644
index 00000000000..f708d5b6d86
--- /dev/null
+++ b/web/src/features/channels/lib/__tests__/yike-balance.test.ts
@@ -0,0 +1,40 @@
+/*
+Copyright (C) 2023-2026 QuantumNous
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+
+For commercial licensing, please contact support@quantumnous.com
+*/
+import assert from 'node:assert/strict'
+import { describe, test } from 'node:test'
+
+import { CHANNEL_TYPE_YIKE } from '../../constants'
+import { formatYikeCredits, isYikeChannel } from '../yike-balance'
+
+describe('Yike credit balance', () => {
+ test('formats native credits without a currency symbol', () => {
+ assert.equal(formatYikeCredits(104, '积分', 'zh-CN'), '104 积分')
+ })
+
+ test('falls back for missing or invalid balances', () => {
+ assert.equal(formatYikeCredits(null, 'Credits', 'en-US'), '-')
+ assert.equal(formatYikeCredits(undefined, 'Credits', 'en-US'), '-')
+ assert.equal(formatYikeCredits(Number.NaN, 'Credits', 'en-US'), '-')
+ })
+
+ test('recognizes only the Yike channel type', () => {
+ assert.equal(isYikeChannel(CHANNEL_TYPE_YIKE), true)
+ assert.equal(isYikeChannel(1), false)
+ })
+})
diff --git a/web/src/features/channels/lib/channel-actions.ts b/web/src/features/channels/lib/channel-actions.ts
index 7efee24d3da..ae7a32fbfd4 100644
--- a/web/src/features/channels/lib/channel-actions.ts
+++ b/web/src/features/channels/lib/channel-actions.ts
@@ -42,6 +42,7 @@ import {
} from '../api'
import { CHANNEL_STATUS, ERROR_MESSAGES, SUCCESS_MESSAGES } from '../constants'
import type { ChannelTestResponse, CopyChannelParams } from '../types'
+import { formatYikeCredits } from './yike-balance'
// ============================================================================
// Query Keys
@@ -374,13 +375,17 @@ export async function handleUpdateChannelBalance(
const response = await updateChannelBalance(id)
if (response.success && response.balance !== undefined) {
const balance = response.balance
+ const formattedBalance =
+ response.unit === 'credits'
+ ? formatYikeCredits(balance, i18next.t('Credits'))
+ : formatCurrencyFromUSD(balance, {
+ digitsLarge: 2,
+ digitsSmall: 4,
+ abbreviate: false,
+ })
toast.success(
i18next.t('Balance updated: {{balance}}', {
- balance: formatCurrencyFromUSD(balance, {
- digitsLarge: 2,
- digitsSmall: 4,
- abbreviate: false,
- }),
+ balance: formattedBalance,
})
)
queryClient?.invalidateQueries({ queryKey: channelsQueryKeys.lists() })
diff --git a/web/src/features/channels/lib/channel-type-config.ts b/web/src/features/channels/lib/channel-type-config.ts
index 8a05b86ee44..d55e6ad5bde 100644
--- a/web/src/features/channels/lib/channel-type-config.ts
+++ b/web/src/features/channels/lib/channel-type-config.ts
@@ -16,7 +16,13 @@ along with this program. If not, see .
For commercial licensing, please contact support@quantumnous.com
*/
-import { CHANNEL_TYPES } from '../constants'
+import {
+ CHANNEL_TYPES,
+ CHANNEL_TYPE_YIKE,
+ TYPE_TO_KEY_PROMPT,
+} from '../constants'
+
+const YIKE_BASE_URL_HINT = 'Yike API base URL hint'
// ============================================================================
// Channel Type Configuration
@@ -164,6 +170,17 @@ export const CHANNEL_TYPE_CONFIGS: Record = {
models: 'Models',
},
},
+ [CHANNEL_TYPE_YIKE]: {
+ id: CHANNEL_TYPE_YIKE,
+ name: CHANNEL_TYPES[CHANNEL_TYPE_YIKE],
+ icon: 'Yike',
+ defaultBaseUrl: 'https://yike.cn-shanghai.aliyuncs.com',
+ hints: {
+ baseUrl: YIKE_BASE_URL_HINT,
+ key: TYPE_TO_KEY_PROMPT[CHANNEL_TYPE_YIKE],
+ models: 'Wonder-Pro,Wonder-Standard,happyhorse-1.1,happyhorse-1.0,wan2.7',
+ },
+ },
}
/**
diff --git a/web/src/features/channels/lib/channel-utils.ts b/web/src/features/channels/lib/channel-utils.ts
index 9424a8521b6..725adee8538 100644
--- a/web/src/features/channels/lib/channel-utils.ts
+++ b/web/src/features/channels/lib/channel-utils.ts
@@ -100,6 +100,7 @@ export function getChannelTypeIcon(type: number): string {
50: 'Kling', // Kling
51: 'Jimeng', // Jimeng
52: 'Vidu', // Vidu
+ 61: 'Yike', // Yike
36: 'Suno', // SunoAPI
55: 'OpenAI', // Sora
54: 'Doubao', // DoubaoVideo
diff --git a/web/src/features/channels/lib/index.ts b/web/src/features/channels/lib/index.ts
index 8c18151ceb5..8d936efbc2a 100644
--- a/web/src/features/channels/lib/index.ts
+++ b/web/src/features/channels/lib/index.ts
@@ -27,3 +27,4 @@ export * from './channel-utils'
export * from './multi-key-utils'
export * from './model-mapping-validation'
export * from './model-categories'
+export * from './yike-balance'
diff --git a/web/src/features/channels/lib/yike-balance.ts b/web/src/features/channels/lib/yike-balance.ts
new file mode 100644
index 00000000000..ea79500fdcd
--- /dev/null
+++ b/web/src/features/channels/lib/yike-balance.ts
@@ -0,0 +1,38 @@
+/*
+Copyright (C) 2023-2026 QuantumNous
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+
+For commercial licensing, please contact support@quantumnous.com
+*/
+import { CHANNEL_TYPE_YIKE } from '../constants'
+
+export function isYikeChannel(channelType: number | null | undefined): boolean {
+ return channelType === CHANNEL_TYPE_YIKE
+}
+
+export function formatYikeCredits(
+ balance: number | null | undefined,
+ unitLabel: string,
+ locale?: string,
+ compact = false
+): string {
+ if (balance == null || !Number.isFinite(balance)) return '-'
+
+ const amount = new Intl.NumberFormat(locale, {
+ maximumFractionDigits: 4,
+ notation: compact ? 'compact' : 'standard',
+ }).format(balance)
+ return `${amount} ${unitLabel}`
+}
diff --git a/web/src/features/channels/types.ts b/web/src/features/channels/types.ts
index f7747fa2121..42d9511239d 100644
--- a/web/src/features/channels/types.ts
+++ b/web/src/features/channels/types.ts
@@ -197,6 +197,7 @@ export interface ChannelBalanceResponse {
message?: string
balance?: number
currency?: string
+ unit?: string
}
export interface FetchModelsResponse {
diff --git a/web/src/i18n/locales/en.json b/web/src/i18n/locales/en.json
index b48096a7fcf..331f6309e42 100644
--- a/web/src/i18n/locales/en.json
+++ b/web/src/i18n/locales/en.json
@@ -279,6 +279,8 @@
"AILS": "AILS",
"AK/SK mode: use AccessKey|SecretAccessKey|Region": "AK/SK mode: use AccessKey|SecretAccessKey|Region",
"Ali": "Alibaba Bailian",
+ "Yike": "Yike (Wonder)",
+ "Yike API base URL hint": "Shanghai: https://yike.cn-shanghai.aliyuncs.com; Singapore: https://yike.ap-southeast-1.aliyuncs.com; HTTPS only",
"Alipay": "Alipay",
"All": "All",
"All API tokens": "All API tokens",
@@ -1124,6 +1126,7 @@
"Coze": "Coze",
"CPU": "CPU",
"CPU Threshold (%)": "CPU Threshold (%)",
+ "Credits": "Credits",
"Create": "Create",
"Create a copy of:": "Create a copy of:",
"Create a key for your app or service": "Create a key for your app or service",
@@ -1673,6 +1676,9 @@
"Enter new tag name or leave empty": "Enter new tag name or leave empty",
"Enter new token to update": "Enter new token to update",
"Enter one API key per line for batch creation": "Enter one API key per line for batch creation",
+ "Enter one complete AccessKeyId|AccessKeySecret pair per line. A separate channel is created for each line, and each channel can query its own credits. Do not put the ID and secret on separate lines.": "Enter one complete AccessKeyId|AccessKeySecret pair per line. A separate channel is created for each line, and each channel can query its own credits. Do not put the ID and secret on separate lines.",
+ "Enter one complete AccessKeyId|AccessKeySecret pair per line. All pairs are stored in one channel and selected randomly or by polling. This mode is for request rotation and does not support querying or summing credits.": "Enter one complete AccessKeyId|AccessKeySecret pair per line. All pairs are stored in one channel and selected randomly or by polling. This mode is for request rotation and does not support querying or summing credits.",
+ "Enter one complete credential pair in the format AccessKeyId|AccessKeySecret. Use a half-width vertical bar (|) with no spaces. This channel can query its credits independently.": "Enter one complete credential pair in the format AccessKeyId|AccessKeySecret. Use a half-width vertical bar (|) with no spaces. This channel can query its credits independently.",
"Enter one key per line for batch creation": "Enter one key per line for batch creation",
"Enter one keyword per line": "Enter one keyword per line",
"Enter only a top-level callback domain, for example https://api.example.com, without any path.": "Enter only a top-level callback domain, for example https://api.example.com, without any path.",
diff --git a/web/src/i18n/locales/fr.json b/web/src/i18n/locales/fr.json
index 638cf9abadd..2f34a79939b 100644
--- a/web/src/i18n/locales/fr.json
+++ b/web/src/i18n/locales/fr.json
@@ -279,6 +279,8 @@
"AILS": "AILS",
"AK/SK mode: use AccessKey|SecretAccessKey|Region": "Mode AK/SK : utiliser AccessKey|SecretAccessKey|Region",
"Ali": "Alibaba Bailian",
+ "Yike": "Yike (Wonder)",
+ "Yike API base URL hint": "Shanghai : https://yike.cn-shanghai.aliyuncs.com ; Singapour : https://yike.ap-southeast-1.aliyuncs.com ; HTTPS uniquement",
"Alipay": "Alipay",
"All": "Tout",
"All API tokens": "Tous les jetons API",
@@ -1124,6 +1126,7 @@
"Coze": "Coze",
"CPU": "Processeur",
"CPU Threshold (%)": "Seuil CPU (%)",
+ "Credits": "Crédits",
"Create": "Créer",
"Create a copy of:": "Créer une copie de :",
"Create a key for your app or service": "Créer une clé pour votre application ou service",
@@ -1673,6 +1676,9 @@
"Enter new tag name or leave empty": "Saisir le nouveau nom de tag ou laisser vide",
"Enter new token to update": "Saisir le nouveau token à mettre à jour",
"Enter one API key per line for batch creation": "Saisissez une clé API par ligne pour la création par lots",
+ "Enter one complete AccessKeyId|AccessKeySecret pair per line. A separate channel is created for each line, and each channel can query its own credits. Do not put the ID and secret on separate lines.": "Saisissez une paire AccessKeyId|AccessKeySecret complète par ligne. Un canal indépendant est créé pour chaque ligne et chacun peut interroger ses propres crédits. Ne placez pas l’ID et le secret sur des lignes distinctes.",
+ "Enter one complete AccessKeyId|AccessKeySecret pair per line. All pairs are stored in one channel and selected randomly or by polling. This mode is for request rotation and does not support querying or summing credits.": "Saisissez une paire AccessKeyId|AccessKeySecret complète par ligne. Toutes les paires sont stockées dans un même canal et sélectionnées aléatoirement ou à tour de rôle. Ce mode sert à répartir les requêtes et ne permet ni d’interroger ni d’additionner les crédits.",
+ "Enter one complete credential pair in the format AccessKeyId|AccessKeySecret. Use a half-width vertical bar (|) with no spaces. This channel can query its credits independently.": "Saisissez une paire d’identifiants complète au format AccessKeyId|AccessKeySecret. Utilisez une barre verticale demi-chasse (|), sans espaces. Ce canal peut interroger ses crédits indépendamment.",
"Enter one key per line for batch creation": "Saisissez une clé par ligne pour la création par lots",
"Enter one keyword per line": "Saisir un mot-clé par ligne",
"Enter only a top-level callback domain, for example https://api.example.com, without any path.": "Saisissez uniquement le domaine de callback principal, par exemple https://api.example.com, sans chemin.",
diff --git a/web/src/i18n/locales/ja.json b/web/src/i18n/locales/ja.json
index 3b9d4ce693c..59c02bd5196 100644
--- a/web/src/i18n/locales/ja.json
+++ b/web/src/i18n/locales/ja.json
@@ -279,6 +279,8 @@
"AILS": "AILS",
"AK/SK mode: use AccessKey|SecretAccessKey|Region": "AK/SKモード: AccessKey | SecretAccessKey | Regionを使用",
"Ali": "アリババ百炼",
+ "Yike": "Yike (Wonder)",
+ "Yike API base URL hint": "上海: https://yike.cn-shanghai.aliyuncs.com、シンガポール: https://yike.ap-southeast-1.aliyuncs.com、HTTPS のみ",
"Alipay": "Alipay",
"All": "すべて",
"All API tokens": "すべての API キー",
@@ -1124,6 +1126,7 @@
"Coze": "Coze",
"CPU": "CPU",
"CPU Threshold (%)": "CPU 閾値 (%)",
+ "Credits": "クレジット",
"Create": "新規作成",
"Create a copy of:": "コピーを作成:",
"Create a key for your app or service": "アプリまたはサービス用のキーを作成",
@@ -1673,6 +1676,9 @@
"Enter new tag name or leave empty": "新しいタグ名を入力するか、空欄にする",
"Enter new token to update": "更新する新しいトークンを入力",
"Enter one API key per line for batch creation": "一括作成のため、1行に1つのAPIキーを入力してください",
+ "Enter one complete AccessKeyId|AccessKeySecret pair per line. A separate channel is created for each line, and each channel can query its own credits. Do not put the ID and secret on separate lines.": "1行ごとに完全な AccessKeyId|AccessKeySecret の組を入力してください。行ごとに独立したチャネルが作成され、各チャネルのクレジットを個別に照会できます。ID と Secret を別々の行に入力しないでください。",
+ "Enter one complete AccessKeyId|AccessKeySecret pair per line. All pairs are stored in one channel and selected randomly or by polling. This mode is for request rotation and does not support querying or summing credits.": "1行ごとに完全な AccessKeyId|AccessKeySecret の組を入力してください。すべての組は1つのチャネルに保存され、ランダムまたは順次ポーリングで選択されます。このモードはリクエストの振り分け用で、クレジットの照会や合計には対応していません。",
+ "Enter one complete credential pair in the format AccessKeyId|AccessKeySecret. Use a half-width vertical bar (|) with no spaces. This channel can query its credits independently.": "AccessKeyId|AccessKeySecret 形式で完全な認証情報を1組入力してください。半角の縦線(|)を使用し、空白は入れないでください。このチャネルはクレジットを個別に照会できます。",
"Enter one key per line for batch creation": "一括作成のため、1行に1つのキーを入力してください",
"Enter one keyword per line": "1行に1つのキーワードを入力",
"Enter only a top-level callback domain, for example https://api.example.com, without any path.": "コールバックのトップレベルドメインのみを入力してください。例: https://api.example.com。パスは含めないでください。",
diff --git a/web/src/i18n/locales/ru.json b/web/src/i18n/locales/ru.json
index 853dc874d46..8847e40bc96 100644
--- a/web/src/i18n/locales/ru.json
+++ b/web/src/i18n/locales/ru.json
@@ -279,6 +279,8 @@
"AILS": "AILS",
"AK/SK mode: use AccessKey|SecretAccessKey|Region": "Режим AK/SK: используйте AccessKey|SecretAccessKey|Region",
"Ali": "Alibaba Байлянь",
+ "Yike": "Yike (Wonder)",
+ "Yike API base URL hint": "Шанхай: https://yike.cn-shanghai.aliyuncs.com; Сингапур: https://yike.ap-southeast-1.aliyuncs.com; только HTTPS",
"Alipay": "Alipay",
"All": "Все",
"All API tokens": "Все API-ключи",
@@ -1124,6 +1126,7 @@
"Coze": "Coze",
"CPU": "ЦП",
"CPU Threshold (%)": "Порог CPU (%)",
+ "Credits": "Кредиты",
"Create": "Создать",
"Create a copy of:": "Создать копию:",
"Create a key for your app or service": "Создайте ключ для приложения или сервиса",
@@ -1673,6 +1676,9 @@
"Enter new tag name or leave empty": "Введите новое имя тега или оставьте пустым",
"Enter new token to update": "Введите новый токен для обновления",
"Enter one API key per line for batch creation": "Введите по одному API-ключу на строку для пакетного создания",
+ "Enter one complete AccessKeyId|AccessKeySecret pair per line. A separate channel is created for each line, and each channel can query its own credits. Do not put the ID and secret on separate lines.": "Введите одну полную пару AccessKeyId|AccessKeySecret в каждой строке. Для каждой строки создается отдельный канал, который может отдельно запрашивать свои кредиты. Не размещайте ID и секрет в разных строках.",
+ "Enter one complete AccessKeyId|AccessKeySecret pair per line. All pairs are stored in one channel and selected randomly or by polling. This mode is for request rotation and does not support querying or summing credits.": "Введите одну полную пару AccessKeyId|AccessKeySecret в каждой строке. Все пары хранятся в одном канале и выбираются случайно или по очереди. Этот режим предназначен для ротации запросов и не поддерживает запрос или суммирование кредитов.",
+ "Enter one complete credential pair in the format AccessKeyId|AccessKeySecret. Use a half-width vertical bar (|) with no spaces. This channel can query its credits independently.": "Введите одну полную пару учетных данных в формате AccessKeyId|AccessKeySecret. Используйте вертикальную черту (|) без пробелов. Этот канал может отдельно запрашивать свои кредиты.",
"Enter one key per line for batch creation": "Введите по одному ключу на строку для пакетного создания",
"Enter one keyword per line": "Введите по одному ключевому слову на строку",
"Enter only a top-level callback domain, for example https://api.example.com, without any path.": "Введите только домен верхнего уровня для callback, например https://api.example.com, без пути.",
diff --git a/web/src/i18n/locales/vi.json b/web/src/i18n/locales/vi.json
index cdc1a12626e..45c3a0e16de 100644
--- a/web/src/i18n/locales/vi.json
+++ b/web/src/i18n/locales/vi.json
@@ -279,6 +279,8 @@
"AILS": "AILS",
"AK/SK mode: use AccessKey|SecretAccessKey|Region": "Chế độ AK/SK: sử dụng AccessKey|SecretAccessKey|Region",
"Ali": "Alibaba Bailian",
+ "Yike": "Yike (Wonder)",
+ "Yike API base URL hint": "Thượng Hải: https://yike.cn-shanghai.aliyuncs.com; Singapore: https://yike.ap-southeast-1.aliyuncs.com; chỉ hỗ trợ HTTPS",
"Alipay": "Alipay",
"All": "All",
"All API tokens": "Tất cả khóa API",
@@ -1124,6 +1126,7 @@
"Coze": "Coze",
"CPU": "CPU",
"CPU Threshold (%)": "Ngưỡng CPU (%)",
+ "Credits": "Điểm",
"Create": "Tạo",
"Create a copy of:": "Tạo bản sao của:",
"Create a key for your app or service": "Tạo khóa cho ứng dụng hoặc dịch vụ của bạn",
@@ -1673,6 +1676,9 @@
"Enter new tag name or leave empty": "Enter new tag name or leave blank",
"Enter new token to update": "Nhập mã thông báo mới để cập nhật",
"Enter one API key per line for batch creation": "Nhập một khóa API mỗi dòng để tạo hàng loạt",
+ "Enter one complete AccessKeyId|AccessKeySecret pair per line. A separate channel is created for each line, and each channel can query its own credits. Do not put the ID and secret on separate lines.": "Nhập một cặp AccessKeyId|AccessKeySecret hoàn chỉnh trên mỗi dòng. Mỗi dòng sẽ tạo một kênh độc lập và từng kênh có thể truy vấn điểm riêng. Không đặt ID và Secret ở hai dòng khác nhau.",
+ "Enter one complete AccessKeyId|AccessKeySecret pair per line. All pairs are stored in one channel and selected randomly or by polling. This mode is for request rotation and does not support querying or summing credits.": "Nhập một cặp AccessKeyId|AccessKeySecret hoàn chỉnh trên mỗi dòng. Tất cả các cặp được lưu trong một kênh và được chọn ngẫu nhiên hoặc luân phiên. Chế độ này chỉ dùng để xoay vòng yêu cầu, không hỗ trợ truy vấn hoặc cộng tổng điểm.",
+ "Enter one complete credential pair in the format AccessKeyId|AccessKeySecret. Use a half-width vertical bar (|) with no spaces. This channel can query its credits independently.": "Nhập một cặp thông tin xác thực hoàn chỉnh theo định dạng AccessKeyId|AccessKeySecret. Dùng dấu gạch đứng (|) không có khoảng trắng. Kênh này có thể truy vấn điểm độc lập.",
"Enter one key per line for batch creation": "Nhập một khóa mỗi dòng để tạo hàng loạt",
"Enter one keyword per line": "Nhập một từ khóa mỗi dòng",
"Enter only a top-level callback domain, for example https://api.example.com, without any path.": "Chỉ nhập tên miền callback cấp cao nhất, ví dụ https://api.example.com, không kèm đường dẫn.",
diff --git a/web/src/i18n/locales/zh-TW.json b/web/src/i18n/locales/zh-TW.json
index f8b5fafd8d2..546b209289a 100644
--- a/web/src/i18n/locales/zh-TW.json
+++ b/web/src/i18n/locales/zh-TW.json
@@ -279,6 +279,8 @@
"AILS": "AILS",
"AK/SK mode: use AccessKey|SecretAccessKey|Region": "AK/SK 模式:使用 AccessKey|SecretAccessKey|Region",
"Ali": "阿里百煉",
+ "Yike": "萬鏡一刻(Yike)",
+ "Yike API base URL hint": "上海:https://yike.cn-shanghai.aliyuncs.com;新加坡:https://yike.ap-southeast-1.aliyuncs.com;僅支援 HTTPS",
"Alipay": "支付寶",
"All": "全部",
"All API tokens": "全部 API 金鑰",
@@ -1124,6 +1126,7 @@
"Coze": "Coze",
"CPU": "CPU",
"CPU Threshold (%)": "CPU 閾值 (%)",
+ "Credits": "積分",
"Create": "建立",
"Create a copy of:": "建立副本:",
"Create a key for your app or service": "為你的套用或服務建立金鑰",
@@ -1673,6 +1676,9 @@
"Enter new tag name or leave empty": "輸入新標籤名稱或留空",
"Enter new token to update": "輸入新令牌以更新",
"Enter one API key per line for batch creation": "每行輸入一個 API 金鑰進行大量建立",
+ "Enter one complete AccessKeyId|AccessKeySecret pair per line. A separate channel is created for each line, and each channel can query its own credits. Do not put the ID and secret on separate lines.": "每行填寫一組完整的 AccessKeyId|AccessKeySecret,系統會按行分別建立獨立渠道,每個渠道都能單獨查詢自己的積分。請勿將 AccessKeyId 和 AccessKeySecret 拆成兩行。",
+ "Enter one complete AccessKeyId|AccessKeySecret pair per line. All pairs are stored in one channel and selected randomly or by polling. This mode is for request rotation and does not support querying or summing credits.": "每行填寫一組完整的 AccessKeyId|AccessKeySecret,所有憑證儲存在同一個渠道,並按隨機或輪詢策略選擇。此模式只用於請求輪換,不支援查詢或合計多組憑證的積分。",
+ "Enter one complete credential pair in the format AccessKeyId|AccessKeySecret. Use a half-width vertical bar (|) with no spaces. This channel can query its credits independently.": "填寫一組完整憑證,格式為 AccessKeyId|AccessKeySecret。中間必須使用英文半形豎線 | 分隔,豎線兩側不要加空格;此渠道可單獨查詢積分。",
"Enter one key per line for batch creation": "每行輸入一個金鑰進行大量建立",
"Enter one keyword per line": "每行輸入一個關鍵詞",
"Enter only a top-level callback domain, for example https://api.example.com, without any path.": "只填寫Callback頂級域名,例如 https://api.example.com,不要帶任何路徑。",
diff --git a/web/src/i18n/locales/zh.json b/web/src/i18n/locales/zh.json
index 842991e714f..e16632b8d33 100644
--- a/web/src/i18n/locales/zh.json
+++ b/web/src/i18n/locales/zh.json
@@ -279,6 +279,8 @@
"AILS": "AILS",
"AK/SK mode: use AccessKey|SecretAccessKey|Region": "AK/SK 模式:使用 AccessKey|SecretAccessKey|Region",
"Ali": "阿里百炼",
+ "Yike": "万镜一刻(Yike)",
+ "Yike API base URL hint": "上海:https://yike.cn-shanghai.aliyuncs.com;新加坡:https://yike.ap-southeast-1.aliyuncs.com;仅支持 HTTPS",
"Alipay": "支付宝",
"All": "全部",
"All API tokens": "全部 API 密钥",
@@ -1124,6 +1126,7 @@
"Coze": "Coze",
"CPU": "CPU",
"CPU Threshold (%)": "CPU 阈值 (%)",
+ "Credits": "积分",
"Create": "新建",
"Create a copy of:": "创建副本:",
"Create a key for your app or service": "为你的应用或服务创建密钥",
@@ -1673,6 +1676,9 @@
"Enter new tag name or leave empty": "输入新标签名称或留空",
"Enter new token to update": "输入新令牌以更新",
"Enter one API key per line for batch creation": "每行输入一个 API 密钥进行批量创建",
+ "Enter one complete AccessKeyId|AccessKeySecret pair per line. A separate channel is created for each line, and each channel can query its own credits. Do not put the ID and secret on separate lines.": "每行填写一组完整的 AccessKeyId|AccessKeySecret,系统会按行分别创建独立渠道,每个渠道都能单独查询自己的积分。不要把 AccessKeyId 和 AccessKeySecret 拆成两行。",
+ "Enter one complete AccessKeyId|AccessKeySecret pair per line. All pairs are stored in one channel and selected randomly or by polling. This mode is for request rotation and does not support querying or summing credits.": "每行填写一组完整的 AccessKeyId|AccessKeySecret,所有凭证保存在同一个渠道,并按随机或轮询策略选择。此模式只用于请求轮换,不支持查询或合计多组凭证的积分。",
+ "Enter one complete credential pair in the format AccessKeyId|AccessKeySecret. Use a half-width vertical bar (|) with no spaces. This channel can query its credits independently.": "填写一组完整凭证,格式为 AccessKeyId|AccessKeySecret。中间必须使用英文半角竖线 | 分隔,竖线两侧不要加空格;此渠道可单独查询积分。",
"Enter one key per line for batch creation": "每行输入一个密钥进行批量创建",
"Enter one keyword per line": "每行输入一个关键词",
"Enter only a top-level callback domain, for example https://api.example.com, without any path.": "只填写回调顶级域名,例如 https://api.example.com,不要带任何路径。",
diff --git a/web/src/lib/lobe-icon.tsx b/web/src/lib/lobe-icon.tsx
index bcce6208dfd..cc38cfedbcc 100644
--- a/web/src/lib/lobe-icon.tsx
+++ b/web/src/lib/lobe-icon.tsx
@@ -29,9 +29,11 @@ import * as LobeIcons from '@lobehub/icons'
import type React from 'react'
import { IconSub2api } from '@/assets/custom/icon-sub2api'
+import { IconYike } from '@/assets/custom/icon-yike'
const CUSTOM_ICONS: Record> = {
Sub2API: IconSub2api,
+ Yike: IconYike,
}
/**