改为 grok 了
This commit is contained in:
127
script.js
127
script.js
@@ -1,4 +1,4 @@
|
||||
// OpenRouter Image Generator - 主要JavaScript逻辑
|
||||
// Grok Image Generator - 主要JavaScript逻辑
|
||||
|
||||
// 全局变量
|
||||
let uploadedImages = [];
|
||||
@@ -6,10 +6,12 @@ let chatHistory = [];
|
||||
let generatedImages = [];
|
||||
let currentSettings = {
|
||||
apiKey: '',
|
||||
baseUrl: 'https://openrouter.ai/api/v1',
|
||||
model: 'google/gemini-2.5-flash-image-preview:free',
|
||||
baseUrl: '',
|
||||
model: 'grok-imagine-1.0',
|
||||
timeout: 600,
|
||||
proxy: ''
|
||||
proxy: '',
|
||||
responseFormat: 'b64_json',
|
||||
n: 1
|
||||
};
|
||||
let currentImageIndex = 0; // 当前查看的图像索引
|
||||
let currentModalInstance = null; // 当前模态框实例
|
||||
@@ -22,12 +24,12 @@ const CONFIG = {
|
||||
MAX_CHAT_HISTORY: 50, // 减少聊天历史记录数量以节省存储空间
|
||||
MAX_GENERATED_IMAGES: 600, // 减少存储的图像数量以防止存储空间溢出
|
||||
STORAGE_KEYS: {
|
||||
SETTINGS: 'openRouterSettings',
|
||||
CHAT_HISTORY: 'openRouterChatHistory',
|
||||
GENERATED_IMAGES: 'openRouterGeneratedImages'
|
||||
SETTINGS: 'grokImageSettings',
|
||||
CHAT_HISTORY: 'grokImageChatHistory',
|
||||
GENERATED_IMAGES: 'grokGeneratedImages'
|
||||
},
|
||||
INDEXED_DB: {
|
||||
NAME: 'OpenRouterImageDB',
|
||||
NAME: 'GrokImageDB',
|
||||
VERSION: 1,
|
||||
STORES: {
|
||||
SETTINGS: 'settings',
|
||||
@@ -39,13 +41,15 @@ const CONFIG = {
|
||||
|
||||
// 错误消息
|
||||
const ERROR_MESSAGES = {
|
||||
NO_API_KEY: '请先输入API Key',
|
||||
CONNECTION_FAILED: '连接失败,请检查网络和API设置',
|
||||
INVALID_RESPONSE: 'API响应格式错误',
|
||||
NO_API_KEY: '请先输入 API Key',
|
||||
NO_BASE_URL: '请先配置 API 地址',
|
||||
CONNECTION_FAILED: '连接失败,请检查网络和 API 设置',
|
||||
INVALID_RESPONSE: 'API 响应格式错误',
|
||||
IMAGE_GENERATION_FAILED: '图像生成失败',
|
||||
FILE_TOO_LARGE: '文件大小超过限制',
|
||||
UNSUPPORTED_FORMAT: '不支持的文件格式',
|
||||
UPLOAD_FAILED: '文件上传失败'
|
||||
UPLOAD_FAILED: '文件上传失败',
|
||||
IMAGE_EDIT_NOT_SUPPORTED: '当前 API 不支持图像编辑,仅支持文本生成图像'
|
||||
};
|
||||
|
||||
// 工具函数
|
||||
@@ -698,35 +702,24 @@ const apiService = {
|
||||
|
||||
// 生成图像
|
||||
generateImage: async function(message, images, settings) {
|
||||
const messages = [
|
||||
{
|
||||
role: 'user',
|
||||
content: [
|
||||
{ type: 'text', text: message }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// 添加上传的图像
|
||||
images.forEach(img => {
|
||||
messages[0].content.push({
|
||||
type: 'image_url',
|
||||
image_url: { url: img.data }
|
||||
});
|
||||
});
|
||||
// 检查是否有上传的图像,如果有则提示不支持
|
||||
if (images && images.length > 0) {
|
||||
console.warn('当前 API 不支持图像编辑,将忽略上传的图像');
|
||||
}
|
||||
|
||||
// 构建请求 payload(符合 OpenAI 图像生成 API 格式)
|
||||
const payload = {
|
||||
model: settings.model,
|
||||
messages: messages,
|
||||
stream: false,
|
||||
"modalities": ["image","text"]
|
||||
prompt: message,
|
||||
n: settings.n || 1,
|
||||
response_format: settings.responseFormat || 'b64_json'
|
||||
};
|
||||
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), settings.timeout * 1000);
|
||||
|
||||
try {
|
||||
const response = await fetch(`${settings.baseUrl}/chat/completions`, {
|
||||
const response = await fetch(`${settings.baseUrl}/v1/images/generations`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${settings.apiKey}`,
|
||||
@@ -739,31 +732,50 @@ const apiService = {
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.error?.message || `HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// 解析响应
|
||||
const choice = data.choices[0];
|
||||
const messageContent = choice.message.content;
|
||||
|
||||
// 解析响应(OpenAI 图像生成 API 格式)
|
||||
const images = [];
|
||||
|
||||
// 提取图像数据并转换为Blob URL,但保留原始base64数据
|
||||
if (choice.message.images) {
|
||||
choice.message.images.forEach(img => {
|
||||
// 确保原始数据是base64格式
|
||||
const originalBase64 = img.image_url.url;
|
||||
const blobUrl = utils.base64ToBlobUrl(originalBase64);
|
||||
images.push(blobUrl);
|
||||
let hasError = false;
|
||||
|
||||
if (data.data && Array.isArray(data.data)) {
|
||||
data.data.forEach(item => {
|
||||
if (item.b64_json) {
|
||||
// 检测 API 返回的错误标记
|
||||
if (item.b64_json === 'error' || item.b64_json === 'Error') {
|
||||
hasError = true;
|
||||
return;
|
||||
}
|
||||
// base64 格式响应
|
||||
const base64Data = `data:image/png;base64,${item.b64_json}`;
|
||||
const blobUrl = utils.base64ToBlobUrl(base64Data);
|
||||
images.push(blobUrl);
|
||||
} else if (item.url) {
|
||||
// 检测 URL 格式的错误标记
|
||||
if (item.url === 'error' || item.url === 'Error') {
|
||||
hasError = true;
|
||||
return;
|
||||
}
|
||||
// URL 格式响应
|
||||
images.push(item.url);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 如果检测到错误标记,抛出错误以触发重试
|
||||
if (hasError) {
|
||||
throw new Error('API 返回错误标记,需要重试');
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
content: messageContent,
|
||||
content: `已生成 ${images.length} 张图像`,
|
||||
images: images,
|
||||
usage: data.usage
|
||||
usage: data.usage || null
|
||||
};
|
||||
} catch (error) {
|
||||
clearTimeout(timeoutId);
|
||||
@@ -1578,6 +1590,7 @@ const uiController = {
|
||||
document.getElementById('model').value = currentSettings.model;
|
||||
document.getElementById('timeout').value = currentSettings.timeout;
|
||||
document.getElementById('proxy').value = currentSettings.proxy;
|
||||
document.getElementById('responseFormat').value = currentSettings.responseFormat || 'b64_json';
|
||||
|
||||
// 加载聊天历史
|
||||
const indexedChatHistory = await indexedDBStorage.getChatHistory();
|
||||
@@ -1756,7 +1769,8 @@ const uiController = {
|
||||
currentSettings.model = document.getElementById('model').value;
|
||||
currentSettings.timeout = parseInt(document.getElementById('timeout').value);
|
||||
currentSettings.proxy = document.getElementById('proxy').value;
|
||||
|
||||
currentSettings.responseFormat = document.getElementById('responseFormat').value;
|
||||
|
||||
const saved = await indexedDBStorage.saveSettings(currentSettings);
|
||||
if (!saved) {
|
||||
console.error('IndexedDB 保存设置失败');
|
||||
@@ -1856,7 +1870,7 @@ const app = {
|
||||
// 初始化"全部下载"按钮的可见性
|
||||
uiController.updateDownloadAllButtonVisibility();
|
||||
|
||||
console.log('OpenRouter Image Generator initialized');
|
||||
console.log('Grok Image Generator initialized');
|
||||
},
|
||||
|
||||
// 初始化事件监听器
|
||||
@@ -1969,6 +1983,21 @@ const app = {
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查 API 地址是否已配置
|
||||
const baseUrl = document.getElementById('baseUrl').value;
|
||||
if (!baseUrl) {
|
||||
utils.showNotification(ERROR_MESSAGES.NO_BASE_URL, 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否有上传的图像,如果有则提示不支持
|
||||
if (uploadedImages && uploadedImages.length > 0) {
|
||||
utils.showNotification(ERROR_MESSAGES.IMAGE_EDIT_NOT_SUPPORTED, 'warning');
|
||||
// 清空上传的图像
|
||||
uploadedImages = [];
|
||||
uiController.updateUploadedImagesDisplay();
|
||||
}
|
||||
|
||||
// 隐藏传统加载状态,使用占位图像代替
|
||||
uiController.hideTraditionalLoading();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user