You've already forked Nano-Banana-AI-Image-Editor
修复 无法上传问题
This commit is contained in:
@@ -4,5 +4,8 @@ VITE_ACCESS_TOKEN=your_access_token_here
|
|||||||
# Gemini API密钥
|
# Gemini API密钥
|
||||||
VITE_GEMINI_API_KEY=your_gemini_api_key_here
|
VITE_GEMINI_API_KEY=your_gemini_api_key_here
|
||||||
|
|
||||||
|
# 上传接口
|
||||||
|
VITE_UPLOAD_API=
|
||||||
|
|
||||||
# 远程资源路径
|
# 远程资源路径
|
||||||
VITE_UPLOAD_ASSET_URL=''
|
VITE_UPLOAD_ASSET_URL=''
|
||||||
@@ -41,6 +41,7 @@ tsc.on('close', (code) => {
|
|||||||
stdio: 'inherit',
|
stdio: 'inherit',
|
||||||
env: {
|
env: {
|
||||||
...process.env,
|
...process.env,
|
||||||
|
NODE_ENV: 'development',
|
||||||
VITE_DEV_SERVER_URL: 'http://localhost:5173',
|
VITE_DEV_SERVER_URL: 'http://localhost:5173',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { app, BrowserWindow, ipcMain } from 'electron';
|
import { app, BrowserWindow, ipcMain, globalShortcut } from 'electron';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
let mainWindow: BrowserWindow | null = null;
|
let mainWindow: BrowserWindow | null = null;
|
||||||
@@ -14,6 +14,7 @@ const createWindow = () => {
|
|||||||
preload: path.join(__dirname, 'preload.js'),
|
preload: path.join(__dirname, 'preload.js'),
|
||||||
nodeIntegration: false,
|
nodeIntegration: false,
|
||||||
contextIsolation: true,
|
contextIsolation: true,
|
||||||
|
devTools: process.env.NODE_ENV === 'development', // 仅在开发环境中启用开发者工具
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -65,6 +66,25 @@ ipcMain.handle('window-is-maximized', () => {
|
|||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
createWindow();
|
createWindow();
|
||||||
|
|
||||||
|
// 在生产环境中禁用开发者工具快捷键
|
||||||
|
if (process.env.NODE_ENV !== 'development') {
|
||||||
|
// 注册全局快捷键拦截
|
||||||
|
globalShortcut.register('Control+Shift+I', () => {
|
||||||
|
// 拦截快捷键,不执行任何操作
|
||||||
|
console.log('Developer tools shortcut intercepted in production');
|
||||||
|
});
|
||||||
|
|
||||||
|
globalShortcut.register('Control+Shift+J', () => {
|
||||||
|
// 拦截快捷键,不执行任何操作
|
||||||
|
console.log('Developer tools console shortcut intercepted in production');
|
||||||
|
});
|
||||||
|
|
||||||
|
globalShortcut.register('F12', () => {
|
||||||
|
// 拦截快捷键,不执行任何操作
|
||||||
|
console.log('Developer tools F12 shortcut intercepted in production');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// On OS X it's common to re-create a window in the app when the
|
// On OS X it's common to re-create a window in the app when the
|
||||||
// dock icon is clicked and there are no other windows open.
|
// dock icon is clicked and there are no other windows open.
|
||||||
app.on('activate', () => {
|
app.on('activate', () => {
|
||||||
@@ -83,5 +103,11 @@ app.on('window-all-closed', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 在应用退出时取消注册所有全局快捷键
|
||||||
|
app.on('will-quit', () => {
|
||||||
|
// 取消注册所有快捷键
|
||||||
|
globalShortcut.unregisterAll();
|
||||||
|
});
|
||||||
|
|
||||||
// In this file you can include the rest of your app's specific main process
|
// In this file you can include the rest of your app's specific main process
|
||||||
// code. You can also put them in separate files and import them here.
|
// code. You can also put them in separate files and import them here.
|
||||||
@@ -34,7 +34,11 @@ tsc.on('close', (code) => {
|
|||||||
build.on('close', (buildCode) => {
|
build.on('close', (buildCode) => {
|
||||||
if (buildCode === 0) {
|
if (buildCode === 0) {
|
||||||
const child = spawn(electron, [appPath], {
|
const child = spawn(electron, [appPath], {
|
||||||
stdio: 'inherit'
|
stdio: 'inherit',
|
||||||
|
env: {
|
||||||
|
...process.env,
|
||||||
|
NODE_ENV: 'production'
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
child.on('close', (code) => {
|
child.on('close', (code) => {
|
||||||
|
|||||||
5514
package-lock.json
generated
5514
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,7 @@
|
|||||||
"test": "jest",
|
"test": "jest",
|
||||||
"test:watch": "jest --watch",
|
"test:watch": "jest --watch",
|
||||||
"electron:dev": "node electron/dev-runner.js",
|
"electron:dev": "node electron/dev-runner.js",
|
||||||
"electron:build": "vite build && copy public\\favicon.svg dist\\ && electron-builder --win --x64",
|
"electron:build": "cross-env NODE_ENV=production vite build && electron-builder --win --x64",
|
||||||
"electron:preview": "node electron/prod-runner.js",
|
"electron:preview": "node electron/prod-runner.js",
|
||||||
"electron:compile": "tsc -p tsconfig.electron.json",
|
"electron:compile": "tsc -p tsconfig.electron.json",
|
||||||
"postinstall": "echo Skipping electron-builder install-app-deps"
|
"postinstall": "echo Skipping electron-builder install-app-deps"
|
||||||
@@ -48,11 +48,17 @@
|
|||||||
"@testing-library/react": "^16.3.0",
|
"@testing-library/react": "^16.3.0",
|
||||||
"@types/jest": "^30.0.0",
|
"@types/jest": "^30.0.0",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
|
"@vitejs/plugin-react": "^5.0.4",
|
||||||
|
"autoprefixer": "^10.4.21",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
|
"electron": "^38.2.1",
|
||||||
"electron-builder": "^26.0.12",
|
"electron-builder": "^26.0.12",
|
||||||
"eslint": "^9.9.1",
|
"eslint": "^9.9.1",
|
||||||
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
|
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.11",
|
"eslint-plugin-react-refresh": "^0.4.11",
|
||||||
"globals": "^15.9.0",
|
"globals": "^15.9.0",
|
||||||
|
"postcss": "^8.5.6",
|
||||||
|
"tailwindcss": "^3.4.15",
|
||||||
"typescript": "^5.5.3",
|
"typescript": "^5.5.3",
|
||||||
"typescript-eslint": "^8.3.0",
|
"typescript-eslint": "^8.3.0",
|
||||||
"vite": "^5.4.2"
|
"vite": "^5.4.2"
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ interface SettingsModalProps {
|
|||||||
export const SettingsModal: React.FC<SettingsModalProps> = ({ open, onOpenChange }) => {
|
export const SettingsModal: React.FC<SettingsModalProps> = ({ open, onOpenChange }) => {
|
||||||
const [accessToken, setAccessToken] = useState('');
|
const [accessToken, setAccessToken] = useState('');
|
||||||
const [geminiApiKey, setGeminiApiKey] = useState('');
|
const [geminiApiKey, setGeminiApiKey] = useState('');
|
||||||
|
const [uploadApiUrl, setUploadApiUrl] = useState('');
|
||||||
const [uploadAssetUrl, setUploadAssetUrl] = useState('');
|
const [uploadAssetUrl, setUploadAssetUrl] = useState('');
|
||||||
|
|
||||||
// 组件挂载时从localStorage加载设置
|
// 组件挂载时从localStorage加载设置
|
||||||
@@ -18,10 +19,12 @@ export const SettingsModal: React.FC<SettingsModalProps> = ({ open, onOpenChange
|
|||||||
if (open) {
|
if (open) {
|
||||||
const savedAccessToken = localStorage.getItem('VITE_ACCESS_TOKEN') || '';
|
const savedAccessToken = localStorage.getItem('VITE_ACCESS_TOKEN') || '';
|
||||||
const savedGeminiApiKey = localStorage.getItem('VITE_GEMINI_API_KEY') || '';
|
const savedGeminiApiKey = localStorage.getItem('VITE_GEMINI_API_KEY') || '';
|
||||||
|
const savedUploadApiUrl = localStorage.getItem('VITE_UPLOAD_API') || '';
|
||||||
const savedUploadAssetUrl = localStorage.getItem('VITE_UPLOAD_ASSET_URL') || '';
|
const savedUploadAssetUrl = localStorage.getItem('VITE_UPLOAD_ASSET_URL') || '';
|
||||||
|
|
||||||
setAccessToken(savedAccessToken);
|
setAccessToken(savedAccessToken);
|
||||||
setGeminiApiKey(savedGeminiApiKey);
|
setGeminiApiKey(savedGeminiApiKey);
|
||||||
|
setUploadApiUrl(savedUploadApiUrl);
|
||||||
setUploadAssetUrl(savedUploadAssetUrl);
|
setUploadAssetUrl(savedUploadAssetUrl);
|
||||||
}
|
}
|
||||||
}, [open]);
|
}, [open]);
|
||||||
@@ -40,6 +43,12 @@ export const SettingsModal: React.FC<SettingsModalProps> = ({ open, onOpenChange
|
|||||||
localStorage.removeItem('VITE_GEMINI_API_KEY');
|
localStorage.removeItem('VITE_GEMINI_API_KEY');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uploadApiUrl) {
|
||||||
|
localStorage.setItem('VITE_UPLOAD_API', uploadApiUrl);
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem('VITE_UPLOAD_API');
|
||||||
|
}
|
||||||
|
|
||||||
if (uploadAssetUrl) {
|
if (uploadAssetUrl) {
|
||||||
localStorage.setItem('VITE_UPLOAD_ASSET_URL', uploadAssetUrl);
|
localStorage.setItem('VITE_UPLOAD_ASSET_URL', uploadAssetUrl);
|
||||||
} else {
|
} else {
|
||||||
@@ -57,10 +66,12 @@ export const SettingsModal: React.FC<SettingsModalProps> = ({ open, onOpenChange
|
|||||||
// 重置为默认值(环境变量中的值)
|
// 重置为默认值(环境变量中的值)
|
||||||
const defaultAccessToken = import.meta.env.VITE_ACCESS_TOKEN || '';
|
const defaultAccessToken = import.meta.env.VITE_ACCESS_TOKEN || '';
|
||||||
const defaultGeminiApiKey = import.meta.env.VITE_GEMINI_API_KEY || '';
|
const defaultGeminiApiKey = import.meta.env.VITE_GEMINI_API_KEY || '';
|
||||||
|
const defaultUploadApiUrl = import.meta.env.VITE_UPLOAD_API || '';
|
||||||
const defaultUploadAssetUrl = import.meta.env.VITE_UPLOAD_ASSET_URL || '';
|
const defaultUploadAssetUrl = import.meta.env.VITE_UPLOAD_ASSET_URL || '';
|
||||||
|
|
||||||
setAccessToken(defaultAccessToken);
|
setAccessToken(defaultAccessToken);
|
||||||
setGeminiApiKey(defaultGeminiApiKey);
|
setGeminiApiKey(defaultGeminiApiKey);
|
||||||
|
setUploadApiUrl(defaultUploadApiUrl);
|
||||||
setUploadAssetUrl(defaultUploadAssetUrl);
|
setUploadAssetUrl(defaultUploadAssetUrl);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -116,6 +127,23 @@ export const SettingsModal: React.FC<SettingsModalProps> = ({ open, onOpenChange
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<label htmlFor="uploadApiUrl" className="text-sm font-medium text-gray-700">
|
||||||
|
上传接口URL
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="uploadApiUrl"
|
||||||
|
type="text"
|
||||||
|
value={uploadApiUrl}
|
||||||
|
onChange={(e) => setUploadApiUrl(e.target.value)}
|
||||||
|
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-yellow-500 focus:border-transparent"
|
||||||
|
placeholder="输入上传接口URL"
|
||||||
|
/>
|
||||||
|
<p className="text-xs text-gray-500">
|
||||||
|
图像上传的目标接口URL
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<label htmlFor="uploadAssetUrl" className="text-sm font-medium text-gray-700">
|
<label htmlFor="uploadAssetUrl" className="text-sm font-medium text-gray-700">
|
||||||
上传资源URL
|
上传资源URL
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { UploadResult } from '../types'
|
|||||||
|
|
||||||
// 上传接口URL
|
// 上传接口URL
|
||||||
// 优先使用localStorage中的URL,如果没有则使用环境变量中的
|
// 优先使用localStorage中的URL,如果没有则使用环境变量中的
|
||||||
const UPLOAD_URL = localStorage.getItem('VITE_UPLOAD_ASSET_URL') || import.meta.env.VITE_UPLOAD_ASSET_URL || 'https://api.pandorastudio.cn/auth/OSSupload'
|
const UPLOAD_URL = localStorage.getItem('VITE_UPLOAD_API') || import.meta.env.VITE_UPLOAD_API || 'https://api.pandorastudio.cn/auth/OSSupload'
|
||||||
|
|
||||||
// 创建一个Map来缓存已上传的图像
|
// 创建一个Map来缓存已上传的图像
|
||||||
const uploadCache = new Map<string, UploadResult>()
|
const uploadCache = new Map<string, UploadResult>()
|
||||||
|
|||||||
Reference in New Issue
Block a user