Compare commits
No commits in common. "b3d151c9f9c62302dea0bc9d1c9320e1b9bf3183" and "98dacf273c9dd30cd13338ae1dbfeba60a828a83" have entirely different histories.
b3d151c9f9
...
98dacf273c
@ -129,7 +129,7 @@ export async function POST(request: NextRequest) {
|
|||||||
cchApiKey: null,
|
cchApiKey: null,
|
||||||
cchApiKeyConfigured: false,
|
cchApiKeyConfigured: false,
|
||||||
defaultModel: 'claude-sonnet-4-5-20250929',
|
defaultModel: 'claude-sonnet-4-5-20250929',
|
||||||
defaultTools: ['web_search', 'web_fetch', 'youdao_translate'],
|
defaultTools: ['web_search', 'web_fetch'],
|
||||||
theme: 'light',
|
theme: 'light',
|
||||||
language: 'zh-CN',
|
language: 'zh-CN',
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
|
|||||||
@ -2042,28 +2042,6 @@ function buildClaudeToolDefinitions(toolIds: string[]) {
|
|||||||
required: ['url'],
|
required: ['url'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
youdao_translate: {
|
|
||||||
name: 'youdao_translate',
|
|
||||||
description: '有道智云高质量多语言翻译。当用户需要翻译文本、句子、段落或询问某个词/短语的翻译时,请使用此工具。支持100+种语言互译,包括中英日韩法德西俄阿拉伯语等。',
|
|
||||||
input_schema: {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
text: {
|
|
||||||
type: 'string',
|
|
||||||
description: '待翻译的文本内容',
|
|
||||||
},
|
|
||||||
from: {
|
|
||||||
type: 'string',
|
|
||||||
description: '源语言代码,如 auto(自动检测)/en(英语)/zh-CHS(简体中文)/ja(日语)/ko(韩语)/fr(法语)/de(德语) 等,默认auto',
|
|
||||||
},
|
|
||||||
to: {
|
|
||||||
type: 'string',
|
|
||||||
description: '目标语言代码,如 zh-CHS(简体中文)/en(英语)/ja(日语)/ko(韩语)/fr(法语)/de(德语) 等,默认zh-CHS',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
required: ['text'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return toolIds
|
return toolIds
|
||||||
@ -2151,31 +2129,6 @@ function buildOpenAIToolDefinitions(toolIds: string[]) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
youdao_translate: {
|
|
||||||
type: 'function',
|
|
||||||
function: {
|
|
||||||
name: 'youdao_translate',
|
|
||||||
description: '有道智云高质量多语言翻译。当用户需要翻译文本、句子、段落或询问某个词/短语的翻译时,请使用此工具。支持100+种语言互译,包括中英日韩法德西俄阿拉伯语等。',
|
|
||||||
parameters: {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
text: {
|
|
||||||
type: 'string',
|
|
||||||
description: '待翻译的文本内容',
|
|
||||||
},
|
|
||||||
from: {
|
|
||||||
type: 'string',
|
|
||||||
description: '源语言代码,如 auto(自动检测)/en(英语)/zh-CHS(简体中文)/ja(日语)/ko(韩语)/fr(法语)/de(德语) 等,默认auto',
|
|
||||||
},
|
|
||||||
to: {
|
|
||||||
type: 'string',
|
|
||||||
description: '目标语言代码,如 zh-CHS(简体中文)/en(英语)/ja(日语)/ko(韩语)/fr(法语)/de(德语) 等,默认zh-CHS',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
required: ['text'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return toolIds
|
return toolIds
|
||||||
@ -2255,29 +2208,6 @@ function buildCodexToolDefinitions(toolIds: string[]) {
|
|||||||
required: ['url'],
|
required: ['url'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
youdao_translate: {
|
|
||||||
type: 'function',
|
|
||||||
name: 'youdao_translate',
|
|
||||||
description: '有道智云高质量多语言翻译。当用户需要翻译文本、句子、段落或询问某个词/短语的翻译时,请使用此工具。支持100+种语言互译,包括中英日韩法德西俄阿拉伯语等。',
|
|
||||||
parameters: {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
text: {
|
|
||||||
type: 'string',
|
|
||||||
description: '待翻译的文本内容',
|
|
||||||
},
|
|
||||||
from: {
|
|
||||||
type: 'string',
|
|
||||||
description: '源语言代码,如 auto(自动检测)/en(英语)/zh-CHS(简体中文)/ja(日语)/ko(韩语)/fr(法语)/de(德语) 等,默认auto',
|
|
||||||
},
|
|
||||||
to: {
|
|
||||||
type: 'string',
|
|
||||||
description: '目标语言代码,如 zh-CHS(简体中文)/en(英语)/ja(日语)/ko(韩语)/fr(法语)/de(德语) 等,默认zh-CHS',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
required: ['text'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return toolIds
|
return toolIds
|
||||||
|
|||||||
@ -8,7 +8,7 @@ const pool = new Pool({
|
|||||||
port: parseInt(process.env.DB_PORT || '35433'),
|
port: parseInt(process.env.DB_PORT || '35433'),
|
||||||
user: process.env.DB_USER || 'postgres',
|
user: process.env.DB_USER || 'postgres',
|
||||||
password: process.env.DB_PASSWORD || 'postgres',
|
password: process.env.DB_PASSWORD || 'postgres',
|
||||||
database: process.env.DB_NAME || 'cchcode_ui',
|
database: process.env.DB_NAME || 'lioncode_ui',
|
||||||
max: 10, // 最大连接数
|
max: 10, // 最大连接数
|
||||||
idleTimeoutMillis: 30000, // 空闲超时
|
idleTimeoutMillis: 30000, // 空闲超时
|
||||||
connectionTimeoutMillis: 5000, // 连接超时
|
connectionTimeoutMillis: 5000, // 连接超时
|
||||||
|
|||||||
@ -15,7 +15,7 @@ async function seedUserSettings() {
|
|||||||
cchApiKeyConfigured: false,
|
cchApiKeyConfigured: false,
|
||||||
metasoApiKeyConfigured: false,
|
metasoApiKeyConfigured: false,
|
||||||
defaultModel: 'claude-sonnet-4-5-20250929',
|
defaultModel: 'claude-sonnet-4-5-20250929',
|
||||||
defaultTools: ['web_search', 'web_fetch', 'youdao_translate'],
|
defaultTools: ['web_search', 'web_fetch', 'mita_search', 'mita_reader'],
|
||||||
theme: 'light',
|
theme: 'light',
|
||||||
language: 'zh-CN',
|
language: 'zh-CN',
|
||||||
enableThinking: false,
|
enableThinking: false,
|
||||||
@ -99,31 +99,6 @@ async function seedTools() {
|
|||||||
isDefault: true,
|
isDefault: true,
|
||||||
sortOrder: 4,
|
sortOrder: 4,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
toolId: 'youdao_translate',
|
|
||||||
name: 'youdao_translate',
|
|
||||||
displayName: 'Translate',
|
|
||||||
description: '有道智云高质量多语言翻译,支持100+种语言互译',
|
|
||||||
icon: 'Languages',
|
|
||||||
inputSchema: {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
text: { type: 'string', description: '待翻译的文本内容' },
|
|
||||||
from: {
|
|
||||||
type: 'string',
|
|
||||||
description: '源语言代码,如 en/zh-CHS/ja/ko/fr/de 等,默认auto自动检测',
|
|
||||||
},
|
|
||||||
to: {
|
|
||||||
type: 'string',
|
|
||||||
description: '目标语言代码,如 zh-CHS/en/ja/ko/fr/de 等,默认zh-CHS简体中文',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
required: ['text'],
|
|
||||||
},
|
|
||||||
isEnabled: true,
|
|
||||||
isDefault: true,
|
|
||||||
sortOrder: 5,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const tool of toolsData) {
|
for (const tool of toolsData) {
|
||||||
|
|||||||
@ -1,11 +1,10 @@
|
|||||||
import { SignJWT, jwtVerify } from 'jose';
|
import { SignJWT, jwtVerify } from 'jose';
|
||||||
import { cookies } from 'next/headers';
|
import { cookies } from 'next/headers';
|
||||||
|
|
||||||
// JWT 密钥(必须通过环境变量配置)
|
// JWT 密钥(生产环境应使用环境变量)
|
||||||
if (!process.env.JWT_SECRET) {
|
const JWT_SECRET = new TextEncoder().encode(
|
||||||
throw new Error('环境变量 JWT_SECRET 未配置,请在 .env.local 中设置');
|
process.env.JWT_SECRET || 'lioncode-jwt-secret-key-2024'
|
||||||
}
|
);
|
||||||
const JWT_SECRET = new TextEncoder().encode(process.env.JWT_SECRET);
|
|
||||||
|
|
||||||
// Token 有效期:7 天
|
// Token 有效期:7 天
|
||||||
const TOKEN_EXPIRY = '7d';
|
const TOKEN_EXPIRY = '7d';
|
||||||
|
|||||||
@ -1,11 +1,8 @@
|
|||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
|
|
||||||
// 加密密钥(32字节 = 256位,用于 AES-256)
|
// 加密密钥(32字节 = 256位,用于 AES-256)
|
||||||
// 必须通过环境变量配置
|
// 生产环境应使用环境变量
|
||||||
if (!process.env.ENCRYPTION_KEY) {
|
const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY || 'lioncode-encryption-key-2024-sec';
|
||||||
throw new Error('环境变量 ENCRYPTION_KEY 未配置,请在 .env.local 中设置');
|
|
||||||
}
|
|
||||||
const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY;
|
|
||||||
|
|
||||||
// 确保密钥长度为32字节
|
// 确保密钥长度为32字节
|
||||||
const getKey = (): Buffer => {
|
const getKey = (): Buffer => {
|
||||||
|
|||||||
@ -2,16 +2,16 @@ import { NextResponse } from 'next/server';
|
|||||||
import type { NextRequest } from 'next/server';
|
import type { NextRequest } from 'next/server';
|
||||||
import { jwtVerify } from 'jose';
|
import { jwtVerify } from 'jose';
|
||||||
|
|
||||||
// JWT 密钥(必须通过环境变量配置)
|
// JWT 密钥
|
||||||
const JWT_SECRET = new TextEncoder().encode(
|
const JWT_SECRET = new TextEncoder().encode(
|
||||||
process.env.JWT_SECRET || ''
|
process.env.JWT_SECRET || 'lioncode-jwt-secret-key-2024'
|
||||||
);
|
);
|
||||||
|
|
||||||
// Cookie 名称
|
// Cookie 名称
|
||||||
const AUTH_COOKIE_NAME = 'lioncode_auth_token';
|
const AUTH_COOKIE_NAME = 'lioncode_auth_token';
|
||||||
|
|
||||||
// 需要登录才能访问的路由
|
// 需要登录才能访问的路由
|
||||||
const protectedRoutes = ['/', '/chat', '/settings', '/assistants', '/notes'];
|
const protectedRoutes = ['/', '/chat', '/settings'];
|
||||||
|
|
||||||
// 公开路由(已登录用户访问会重定向到首页)
|
// 公开路由(已登录用户访问会重定向到首页)
|
||||||
const publicRoutes = ['/login', '/register', '/reset-password'];
|
const publicRoutes = ['/login', '/register', '/reset-password'];
|
||||||
|
|||||||
@ -42,13 +42,6 @@ import {
|
|||||||
type MetasoReaderInput,
|
type MetasoReaderInput,
|
||||||
type MetasoReaderResponse,
|
type MetasoReaderResponse,
|
||||||
} from './metasoReader';
|
} from './metasoReader';
|
||||||
import {
|
|
||||||
translate,
|
|
||||||
formatTranslateResult,
|
|
||||||
formatTranslateResultShort,
|
|
||||||
type TranslateInput,
|
|
||||||
type TranslateResponse,
|
|
||||||
} from './translate';
|
|
||||||
import { shouldUsePyodide, analyzeCode, type LoadingCallback } from './codeAnalyzer';
|
import { shouldUsePyodide, analyzeCode, type LoadingCallback } from './codeAnalyzer';
|
||||||
|
|
||||||
// 导出代码分析函数供外部使用
|
// 导出代码分析函数供外部使用
|
||||||
@ -215,22 +208,6 @@ export async function executeTool(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'youdao_translate': {
|
|
||||||
const text = String(input.text || '');
|
|
||||||
const from = input.from ? String(input.from) : 'auto';
|
|
||||||
const to = input.to ? String(input.to) : 'zh-CHS';
|
|
||||||
|
|
||||||
const translateInput: TranslateInput = { text, from, to };
|
|
||||||
const response: TranslateResponse = await translate(translateInput);
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: response.success,
|
|
||||||
fullResult: formatTranslateResult(response, text),
|
|
||||||
displayResult: formatTranslateResultShort(response, text),
|
|
||||||
rawData: response,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
@ -278,11 +255,5 @@ export function getAvailableTools() {
|
|||||||
description: '秘塔AI网页读取,返回Markdown格式',
|
description: '秘塔AI网页读取,返回Markdown格式',
|
||||||
icon: '📄',
|
icon: '📄',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: 'youdao_translate',
|
|
||||||
name: '翻译',
|
|
||||||
description: '有道智云高质量多语言翻译,支持100+种语言',
|
|
||||||
icon: '🌐',
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,314 +0,0 @@
|
|||||||
/**
|
|
||||||
* 有道翻译工具服务
|
|
||||||
* 使用有道智云API实现高质量多语言翻译
|
|
||||||
*
|
|
||||||
* API文档: https://ai.youdao.com/DOCSIRMA/html/trans/api/wbfy/index.html
|
|
||||||
*/
|
|
||||||
|
|
||||||
import crypto from 'crypto';
|
|
||||||
|
|
||||||
// ============== 类型定义 ==============
|
|
||||||
|
|
||||||
export interface TranslateInput {
|
|
||||||
/** 待翻译文本 */
|
|
||||||
text: string;
|
|
||||||
/** 源语言代码,默认auto自动检测 */
|
|
||||||
from?: string;
|
|
||||||
/** 目标语言代码,默认zh-CHS简体中文 */
|
|
||||||
to?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TranslateResponse {
|
|
||||||
/** 是否成功 */
|
|
||||||
success: boolean;
|
|
||||||
/** 翻译结果 */
|
|
||||||
translation?: string;
|
|
||||||
/** 检测到的源语言 */
|
|
||||||
from?: string;
|
|
||||||
/** 目标语言 */
|
|
||||||
to?: string;
|
|
||||||
/** 错误信息 */
|
|
||||||
error?: string;
|
|
||||||
/** 原始API响应 */
|
|
||||||
rawResponse?: YoudaoApiResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 有道API原始响应 */
|
|
||||||
interface YoudaoApiResponse {
|
|
||||||
errorCode: string;
|
|
||||||
query?: string;
|
|
||||||
translation?: string[];
|
|
||||||
l?: string;
|
|
||||||
dict?: { url: string };
|
|
||||||
webdict?: { url: string };
|
|
||||||
tSpeakUrl?: string;
|
|
||||||
speakUrl?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============== 有道API配置 ==============
|
|
||||||
|
|
||||||
const YOUDAO_APP_KEY = process.env.YOUDAO_APP_KEY || '';
|
|
||||||
const YOUDAO_APP_SECRET = process.env.YOUDAO_APP_SECRET || '';
|
|
||||||
const YOUDAO_API_URL = 'https://openapi.youdao.com/api';
|
|
||||||
|
|
||||||
// ============== 错误码映射 ==============
|
|
||||||
|
|
||||||
const ERROR_CODE_MAP: Record<string, string> = {
|
|
||||||
'101': '缺少必填参数',
|
|
||||||
'102': '不支持的语言类型',
|
|
||||||
'103': '翻译文本过长(最大5000字符)',
|
|
||||||
'108': '应用ID无效',
|
|
||||||
'110': '无相关服务的有效应用',
|
|
||||||
'111': '开发者账号无效',
|
|
||||||
'112': '请求服务无效',
|
|
||||||
'113': '翻译文本不能为空',
|
|
||||||
'202': '签名检验失败',
|
|
||||||
'203': '访问IP地址不在可访问IP列表',
|
|
||||||
'206': '时间戳无效导致签名校验失败',
|
|
||||||
'207': '重放请求',
|
|
||||||
'301': '辞典查询失败',
|
|
||||||
'302': '翻译查询失败',
|
|
||||||
'303': '服务端异常',
|
|
||||||
'401': '账户已欠费',
|
|
||||||
'411': '访问频率受限',
|
|
||||||
'412': '长请求过于频繁',
|
|
||||||
};
|
|
||||||
|
|
||||||
// ============== 工具函数 ==============
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成SHA256签名
|
|
||||||
*/
|
|
||||||
function generateSign(
|
|
||||||
appKey: string,
|
|
||||||
input: string,
|
|
||||||
salt: string,
|
|
||||||
curtime: string,
|
|
||||||
appSecret: string
|
|
||||||
): string {
|
|
||||||
const signStr = appKey + input + salt + curtime + appSecret;
|
|
||||||
return crypto.createHash('sha256').update(signStr).digest('hex');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 计算input参数(处理长文本截断)
|
|
||||||
* 规则:文本长度>20时,取前10字符+长度+后10字符
|
|
||||||
*/
|
|
||||||
function truncate(q: string): string {
|
|
||||||
const len = q.length;
|
|
||||||
if (len <= 20) return q;
|
|
||||||
return q.substring(0, 10) + len + q.substring(len - 10, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取错误信息
|
|
||||||
*/
|
|
||||||
function getErrorMessage(errorCode: string): string {
|
|
||||||
return ERROR_CODE_MAP[errorCode] || `未知错误 (错误码: ${errorCode})`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============== 语言代码映射 ==============
|
|
||||||
|
|
||||||
/** 常用语言代码对照表 */
|
|
||||||
export const LANGUAGE_MAP: Record<string, string> = {
|
|
||||||
// 自动检测
|
|
||||||
'auto': '自动检测',
|
|
||||||
// 中文
|
|
||||||
'zh-CHS': '简体中文',
|
|
||||||
'zh-CHT': '繁体中文',
|
|
||||||
// 主要语言
|
|
||||||
'en': '英语',
|
|
||||||
'ja': '日语',
|
|
||||||
'ko': '韩语',
|
|
||||||
'fr': '法语',
|
|
||||||
'de': '德语',
|
|
||||||
'es': '西班牙语',
|
|
||||||
'pt': '葡萄牙语',
|
|
||||||
'it': '意大利语',
|
|
||||||
'ru': '俄语',
|
|
||||||
'ar': '阿拉伯语',
|
|
||||||
// 其他常用语言
|
|
||||||
'vi': '越南语',
|
|
||||||
'th': '泰语',
|
|
||||||
'id': '印度尼西亚语',
|
|
||||||
'ms': '马来语',
|
|
||||||
'hi': '印地语',
|
|
||||||
'nl': '荷兰语',
|
|
||||||
'pl': '波兰语',
|
|
||||||
'tr': '土耳其语',
|
|
||||||
'uk': '乌克兰语',
|
|
||||||
'sv': '瑞典语',
|
|
||||||
'da': '丹麦语',
|
|
||||||
'no': '挪威语',
|
|
||||||
'fi': '芬兰语',
|
|
||||||
'el': '希腊语',
|
|
||||||
'cs': '捷克语',
|
|
||||||
'hu': '匈牙利语',
|
|
||||||
'ro': '罗马尼亚语',
|
|
||||||
'bg': '保加利亚语',
|
|
||||||
'he': '希伯来语',
|
|
||||||
'yue': '粤语',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取语言名称
|
|
||||||
*/
|
|
||||||
export function getLanguageName(code: string): string {
|
|
||||||
return LANGUAGE_MAP[code] || code;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============== 主翻译函数 ==============
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行翻译
|
|
||||||
* @param input 翻译输入参数
|
|
||||||
* @returns 翻译响应
|
|
||||||
*/
|
|
||||||
export async function translate(input: TranslateInput): Promise<TranslateResponse> {
|
|
||||||
const { text, from = 'auto', to = 'zh-CHS' } = input;
|
|
||||||
|
|
||||||
// API Key 验证
|
|
||||||
if (!YOUDAO_APP_KEY || !YOUDAO_APP_SECRET) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: '有道翻译 API 未配置,请在环境变量中设置 YOUDAO_APP_KEY 和 YOUDAO_APP_SECRET',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 参数验证
|
|
||||||
if (!text || text.trim().length === 0) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: '翻译文本不能为空',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (text.length > 5000) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: '翻译文本过长,最大支持5000字符',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 生成请求参数
|
|
||||||
const salt = crypto.randomUUID();
|
|
||||||
const curtime = Math.round(Date.now() / 1000).toString();
|
|
||||||
const sign = generateSign(
|
|
||||||
YOUDAO_APP_KEY,
|
|
||||||
truncate(text),
|
|
||||||
salt,
|
|
||||||
curtime,
|
|
||||||
YOUDAO_APP_SECRET
|
|
||||||
);
|
|
||||||
|
|
||||||
// 构建请求体
|
|
||||||
const params = new URLSearchParams({
|
|
||||||
q: text,
|
|
||||||
from,
|
|
||||||
to,
|
|
||||||
appKey: YOUDAO_APP_KEY,
|
|
||||||
salt,
|
|
||||||
sign,
|
|
||||||
signType: 'v3',
|
|
||||||
curtime,
|
|
||||||
});
|
|
||||||
|
|
||||||
// 发送请求
|
|
||||||
const response = await fetch(YOUDAO_API_URL, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
|
||||||
},
|
|
||||||
body: params.toString(),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: `HTTP请求失败: ${response.status} ${response.statusText}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const data: YoudaoApiResponse = await response.json();
|
|
||||||
|
|
||||||
// 检查API返回结果
|
|
||||||
if (data.errorCode === '0') {
|
|
||||||
// 解析语言方向 (如 "en2zh-CHS")
|
|
||||||
const langParts = data.l?.split('2') || [from, to];
|
|
||||||
const detectedFrom = langParts[0] || from;
|
|
||||||
const detectedTo = langParts[1] || to;
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
translation: data.translation?.join('\n') || '',
|
|
||||||
from: detectedFrom,
|
|
||||||
to: detectedTo,
|
|
||||||
rawResponse: data,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: getErrorMessage(data.errorCode),
|
|
||||||
rawResponse: data,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Translate API error:', error);
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: error instanceof Error ? error.message : '翻译请求失败',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============== 格式化函数 ==============
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 格式化翻译结果(完整版 - 发送给AI)
|
|
||||||
*/
|
|
||||||
export function formatTranslateResult(
|
|
||||||
response: TranslateResponse,
|
|
||||||
originalText: string
|
|
||||||
): string {
|
|
||||||
if (!response.success) {
|
|
||||||
return `翻译失败: ${response.error}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fromLang = getLanguageName(response.from || 'auto');
|
|
||||||
const toLang = getLanguageName(response.to || 'zh-CHS');
|
|
||||||
|
|
||||||
let result = `## 翻译结果\n\n`;
|
|
||||||
result += `**源语言**: ${fromLang}\n`;
|
|
||||||
result += `**目标语言**: ${toLang}\n\n`;
|
|
||||||
result += `### 原文\n${originalText}\n\n`;
|
|
||||||
result += `### 译文\n${response.translation}`;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 格式化翻译结果(简短版 - 显示给用户)
|
|
||||||
*/
|
|
||||||
export function formatTranslateResultShort(
|
|
||||||
response: TranslateResponse,
|
|
||||||
originalText: string
|
|
||||||
): string {
|
|
||||||
if (!response.success) {
|
|
||||||
return `翻译失败: ${response.error}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fromLang = getLanguageName(response.from || 'auto');
|
|
||||||
const toLang = getLanguageName(response.to || 'zh-CHS');
|
|
||||||
|
|
||||||
// 截取原文预览(最多30字符)
|
|
||||||
const textPreview = originalText.length > 30
|
|
||||||
? originalText.substring(0, 30) + '...'
|
|
||||||
: originalText;
|
|
||||||
|
|
||||||
let result = `> 🌐 已翻译「${textPreview}」\n`;
|
|
||||||
result += `> **${fromLang}** → **${toLang}**\n\n`;
|
|
||||||
result += `${response.translation}`;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user