From 617c22b00a9b5dfa42dba2ca94f763b0ec3c8792 Mon Sep 17 00:00:00 2001 From: huty Date: Fri, 26 Dec 2025 16:28:41 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=87=B3=20v0.2.0=5F20251226?= =?UTF-8?q?=20=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.tsx | 54 ++++++++++++++--- components/Select.tsx | 14 ++--- components/Toast.tsx | 64 ++++++++++++++++++++ releases/WORK-SH-XPC-SQL-0.2.0_20251226.zip | Bin 0 -> 18020 bytes services/gemini.ts | 9 ++- types.ts | 1 + 6 files changed, 124 insertions(+), 18 deletions(-) create mode 100644 components/Toast.tsx create mode 100644 releases/WORK-SH-XPC-SQL-0.2.0_20251226.zip diff --git a/App.tsx b/App.tsx index 1f18297..e096878 100644 --- a/App.tsx +++ b/App.tsx @@ -5,6 +5,7 @@ import { Button } from './components/Button'; import { TextArea } from './components/TextArea'; import { Select } from './components/Select'; import { SettingsModal } from './components/SettingsModal'; +import { Toast, ToastType } from './components/Toast'; import { LoadingState, DatabaseType } from './types'; // Default placeholders to help the user understand what to input @@ -49,8 +50,15 @@ const DB_OPTIONS = [ { value: 'SQLite', label: 'SQLite' }, ]; +const MODEL_OPTIONS = [ + { value: 'gemini-3-pro-preview', label: 'Gemini 3.0 Pro (推荐 - 强逻辑)' }, + { value: 'gemini-3-flash-preview', label: 'Gemini 3.0 Flash (极速)' }, + { value: 'gemini-2.5-flash', label: 'Gemini 2.5 Flash' }, +]; + const App: React.FC = () => { const [databaseType, setDatabaseType] = useState('MySQL'); + const [model, setModel] = useState('gemini-3-flash-preview'); const [tableStructure, setTableStructure] = useState(''); const [dictionaryData, setDictionaryData] = useState(''); const [requirement, setRequirement] = useState(''); @@ -63,6 +71,9 @@ const App: React.FC = () => { const [apiKey, setApiKey] = useState(''); const [isSettingsOpen, setIsSettingsOpen] = useState(false); + // Toast Notification State + const [toast, setToast] = useState<{message: string, type: ToastType, id: number} | null>(null); + useEffect(() => { const storedKey = localStorage.getItem('user_api_key'); if (storedKey) { @@ -70,14 +81,22 @@ const App: React.FC = () => { } }, []); + const showToast = (message: string, type: ToastType = 'success') => { + setToast({ message, type, id: Date.now() }); + }; + + const closeToast = () => setToast(null); + const handleSaveApiKey = (key: string) => { setApiKey(key); localStorage.setItem('user_api_key', key); setIsSettingsOpen(false); + showToast("API Key 配置已保存", "success"); }; const handleGenerate = async () => { if (!tableStructure.trim() || !requirement.trim()) { + showToast("请至少填写表结构和查询需求", "error"); setErrorMsg("请至少填写表结构和查询需求。"); return; } @@ -92,24 +111,38 @@ const App: React.FC = () => { dictionaryData, requirement, databaseType, + model, apiKey // Pass the custom API key }); setGeneratedSql(sql); setStatus(LoadingState.SUCCESS); + showToast("SQL 查询生成成功", "success"); } catch (err: any) { setErrorMsg(err.message || "未知错误"); setStatus(LoadingState.ERROR); + showToast(err.message || "生成失败,请重试", "error"); } }; const copyToClipboard = () => { if (generatedSql) { navigator.clipboard.writeText(generatedSql); + showToast("已复制到剪贴板", "success"); } }; return ( -
+
+ {/* Toast Notification Container */} + {toast && ( + + )} + setIsSettingsOpen(false)} @@ -147,13 +180,18 @@ const App: React.FC = () => { {/* Left Panel: Inputs */}
-
+
setModel(e.target.value)} />
@@ -207,7 +245,7 @@ const App: React.FC = () => {
-

生成结果 ({databaseType})

+

生成结果 ({databaseType} by {MODEL_OPTIONS.find(m => m.value === model)?.label?.split('(')[0].trim()})

{status === LoadingState.SUCCESS && (
)} @@ -231,7 +269,7 @@ const App: React.FC = () => {
- 正在分析表结构并构建 {databaseType} 查询... + 正在使用 {MODEL_OPTIONS.find(m => m.value === model)?.label.split('(')[0]} 构建查询...
)} @@ -256,4 +294,4 @@ const App: React.FC = () => { ); }; -export default App; \ No newline at end of file +export default App; diff --git a/components/Select.tsx b/components/Select.tsx index 6edee66..52e8ff6 100644 --- a/components/Select.tsx +++ b/components/Select.tsx @@ -9,18 +9,18 @@ interface SelectProps extends React.SelectHTMLAttributes { export const Select: React.FC = ({ label, options, helperText, className = '', ...props }) => { return ( -
+
-
-
+
-
- - +
+
diff --git a/components/Toast.tsx b/components/Toast.tsx new file mode 100644 index 0000000..59ee2d6 --- /dev/null +++ b/components/Toast.tsx @@ -0,0 +1,64 @@ + +import React, { useEffect, useState } from 'react'; + +export type ToastType = 'success' | 'error' | 'info'; + +export interface ToastProps { + message: string; + type: ToastType; + onClose: () => void; +} + +export const Toast: React.FC = ({ message, type, onClose }) => { + const [visible, setVisible] = useState(false); + + useEffect(() => { + // Start entry animation + requestAnimationFrame(() => setVisible(true)); + + // Auto dismiss + const timer = setTimeout(() => { + setVisible(false); + // Allow exit animation to complete before unmounting + setTimeout(onClose, 300); + }, 3000); + + return () => clearTimeout(timer); + }, [onClose]); + + const baseClasses = "fixed top-6 left-1/2 transform -translate-x-1/2 z-[100] flex items-center gap-3 px-5 py-3 rounded-lg shadow-xl text-white font-medium text-sm transition-all duration-300 ease-out"; + + const typeClasses = { + success: "bg-emerald-600 ring-1 ring-emerald-500", + error: "bg-rose-600 ring-1 ring-rose-500", + info: "bg-indigo-600 ring-1 ring-indigo-500" + }; + + // Animation states + const opacityClass = visible ? "opacity-100 translate-y-0 scale-100" : "opacity-0 -translate-y-4 scale-95"; + + const icons = { + success: ( + + + + ), + error: ( + + + + ), + info: ( + + + + ) + }; + + return ( +
+ {icons[type]} + {message} +
+ ); +}; diff --git a/releases/WORK-SH-XPC-SQL-0.2.0_20251226.zip b/releases/WORK-SH-XPC-SQL-0.2.0_20251226.zip new file mode 100644 index 0000000000000000000000000000000000000000..c8d559c12250e310d612a325e9d553ef5a60127d GIT binary patch literal 18020 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 literal 0 HcmV?d00001 diff --git a/services/gemini.ts b/services/gemini.ts index e6cfd4c..6e7a743 100644 --- a/services/gemini.ts +++ b/services/gemini.ts @@ -42,12 +42,15 @@ export const generateSql = async (requestData: SqlGenerationRequest): Promise