mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-05-07 04:22:48 +08:00
- 消息管理:新增聊天气泡的重试、编辑与单条删除功能及相对应的持久化状态函数 - 快捷操作:支持长文一键滑动到底端,并在代码块内增加SQL一键送入编辑器的快捷执行机制 - 视觉优化:深化AI回复背景沉浸感,重绘AI洞察按钮并移除设置面板所有的冗余紫色调 - 设置调优:放宽模型初始必填限制,新增内置系统提示词(Builtin Prompt)全览面板
183 lines
10 KiB
HTML
183 lines
10 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>AI UI Brainstorming Prototypes</title>
|
||
<!-- React & ReactDOM -->
|
||
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
|
||
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
|
||
<!-- Babel -->
|
||
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
|
||
<!-- Ant Design -->
|
||
<script src="https://unpkg.com/dayjs/dayjs.min.js"></script>
|
||
<script src="https://unpkg.com/antd/dist/antd.min.js"></script>
|
||
<link rel="stylesheet" href="https://unpkg.com/antd/dist/reset.css" />
|
||
<!-- Icons -->
|
||
<script src="https://unpkg.com/@ant-design/icons/dist/index.umd.js"></script>
|
||
<style>
|
||
body { padding: 40px; background: #f0f2f5; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial; }
|
||
.prototype-container { display: flex; gap: 40px; }
|
||
.prototype-column { flex: 1; max-width: 600px; background: white; border-radius: 12px; box-shadow: 0 4px 12px rgba(0,0,0,0.05); overflow: hidden; }
|
||
.prototype-header { padding: 16px 24px; border-bottom: 1px solid #f0f0f0; background: #fafafa; font-weight: bold; }
|
||
.prototype-body { padding: 24px; }
|
||
|
||
/* Default App Theme Colors (Light Mode) */
|
||
:root {
|
||
--gn-border: rgba(16,24,40,0.08);
|
||
--gn-bg: rgba(255,255,255,0.84);
|
||
--gn-text: #162033;
|
||
--gn-muted: rgba(16,24,40,0.55);
|
||
--gn-primary: #1677ff;
|
||
--gn-primary-bg: rgba(24,144,255,0.1);
|
||
}
|
||
|
||
/* V1 Styles: Professional List */
|
||
.v1-list-item {
|
||
display: flex; align-items: center; justify-content: space-between;
|
||
padding: 12px 16px; margin-bottom: 8px; border-radius: 8px;
|
||
border: 1px solid transparent; cursor: pointer; transition: all 0.2s;
|
||
}
|
||
.v1-list-item:hover { background: #f5f5f5; }
|
||
.v1-list-item.selected {
|
||
background: var(--gn-primary-bg); border-color: var(--gn-primary);
|
||
}
|
||
|
||
/* V2 Styles: Refined Cards (ConnectionModal Style) */
|
||
.v2-card-grid {
|
||
display: grid; grid-template-columns: 1fr 1fr; gap: 12px;
|
||
}
|
||
.v2-card {
|
||
padding: 16px; border-radius: 12px; border: 1px solid var(--gn-border);
|
||
cursor: pointer; transition: all 0.2s; background: white;
|
||
box-shadow: inset 0 0 0 1px rgba(16,24,40,0.01);
|
||
}
|
||
.v2-card:hover { border-color: #d9d9d9; background: #fafafa; }
|
||
.v2-card.selected {
|
||
border-color: var(--gn-primary); box-shadow: 0 0 0 1px var(--gn-primary) inset;
|
||
}
|
||
|
||
.section-title { font-size: 13px; font-weight: 600; color: var(--gn-muted); margin-bottom: 12px; text-transform: uppercase; letter-spacing: 0.5px; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="root"></div>
|
||
<script type="text/babel">
|
||
const { useState } = React;
|
||
const { Input, Slider, Select, Button, Form, ConfigProvider } = antd;
|
||
const { ThunderboltOutlined, CloudOutlined, ExperimentOutlined, AppstoreOutlined, SettingOutlined, LinkOutlined, KeyOutlined } = icons;
|
||
|
||
const PROVIDERS = [
|
||
{ key: 'openai', label: 'OpenAI', icon: <ThunderboltOutlined />, desc: 'GPT-4o / o1' },
|
||
{ key: 'deepseek', label: 'DeepSeek', icon: <ThunderboltOutlined />, desc: 'V3 / R1' },
|
||
{ key: 'anthropic', label: 'Claude', icon: <ExperimentOutlined />, desc: 'Sonnet 3.5' },
|
||
{ key: 'custom', label: '自定义', icon: <AppstoreOutlined />, desc: '通用 API' },
|
||
];
|
||
|
||
const V1ListDesign = () => {
|
||
const [selected, setSelected] = useState('openai');
|
||
return (
|
||
<div className="prototype-column">
|
||
<div className="prototype-header">方案一:IDE 专业列表风格 (更克制、无彩色渐变)</div>
|
||
<div className="prototype-body">
|
||
<div className="section-title">提供商选择</div>
|
||
<div style={{ marginBottom: 24, padding: 8, background: '#fafafa', borderRadius: 10, border: '1px solid #f0f0f0' }}>
|
||
{PROVIDERS.map(p => (
|
||
<div key={p.key} className={`v1-list-item ${selected === p.key ? 'selected' : ''}`} onClick={() => setSelected(p.key)}>
|
||
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
||
<div style={{
|
||
width: 32, height: 32, borderRadius: 6, display: 'grid', placeItems: 'center',
|
||
background: selected === p.key ? '#1677ff' : '#e6f4ff',
|
||
color: selected === p.key ? '#fff' : '#1677ff', fontSize: 16
|
||
}}>
|
||
{p.icon}
|
||
</div>
|
||
<div>
|
||
<div style={{ fontWeight: 500, color: 'var(--gn-text)', fontSize: 14 }}>{p.label}</div>
|
||
<div style={{ fontSize: 12, color: 'var(--gn-muted)' }}>{p.desc}</div>
|
||
</div>
|
||
</div>
|
||
<div style={{ width: 16, height: 16, borderRadius: '50%', border: `2px solid ${selected === p.key ? 'var(--gn-primary)' : '#d9d9d9'}`, padding: 2 }}>
|
||
{selected === p.key && <div style={{ width: '100%', height: '100%', background: 'var(--gn-primary)', borderRadius: '50%' }} />}
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
|
||
<div className="section-title">连接配置 (紧凑表单)</div>
|
||
<Form layout="vertical" size="middle">
|
||
<Form.Item label="API Endpoint">
|
||
<Input placeholder="https://api.openai.com/v1" prefix={<LinkOutlined style={{color: 'var(--gn-muted)'}}/>} />
|
||
</Form.Item>
|
||
<Form.Item label="API Key">
|
||
<Input.Password placeholder="sk-..." prefix={<KeyOutlined style={{color: 'var(--gn-muted)'}}/>} />
|
||
</Form.Item>
|
||
<Form.Item label="Model Name">
|
||
<Input placeholder="gpt-4o" prefix={<AppstoreOutlined style={{color: 'var(--gn-muted)'}}/>} />
|
||
</Form.Item>
|
||
</Form>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
const V2CardDesign = () => {
|
||
const [selected, setSelected] = useState('openai');
|
||
return (
|
||
<div className="prototype-column">
|
||
<div className="prototype-header">方案二:GoNavi 统一卡片风格 (类似 ConnectionModal)</div>
|
||
<div className="prototype-body">
|
||
<div className="section-title">选择服务提供商</div>
|
||
<div className="v2-card-grid" style={{ marginBottom: 24 }}>
|
||
{PROVIDERS.map(p => (
|
||
<div key={p.key} className={`v2-card ${selected === p.key ? 'selected' : ''}`} onClick={() => setSelected(p.key)}>
|
||
<div style={{ display: 'flex', alignItems: 'flex-start', gap: 12 }}>
|
||
<div style={{ color: selected === p.key ? 'var(--gn-primary)' : 'var(--gn-muted)', fontSize: 20, marginTop: 2 }}>
|
||
{p.icon}
|
||
</div>
|
||
<div>
|
||
<div style={{ fontWeight: 600, color: 'var(--gn-text)', fontSize: 14 }}>{p.label}</div>
|
||
<div style={{ fontSize: 12, color: 'var(--gn-muted)', marginTop: 4 }}>{p.desc}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
|
||
<div style={{ padding: 20, borderRadius: 12, border: '1px solid var(--gn-border)', background: '#fafafa' }}>
|
||
<div className="section-title" style={{ marginTop: 0 }}>认证与设置</div>
|
||
<Form layout="horizontal" labelCol={{ span: 6 }} wrapperCol={{ span: 18 }} size="middle">
|
||
<Form.Item label="Endpoint" style={{ marginBottom: 16 }}>
|
||
<Input placeholder="https://api..." />
|
||
</Form.Item>
|
||
<Form.Item label="API Key" style={{ marginBottom: 16 }}>
|
||
<Input.Password placeholder="sk-..." />
|
||
</Form.Item>
|
||
<Form.Item label="模型名称" style={{ marginBottom: 0 }}>
|
||
<Input placeholder="例如 gpt-4o" />
|
||
</Form.Item>
|
||
</Form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
const App = () => (
|
||
<ConfigProvider theme={{ token: { colorPrimary: '#1677ff', borderRadius: 6 } }}>
|
||
<div style={{ marginBottom: 24 }}>
|
||
<h1 style={{ fontSize: 24, margin: 0 }}>AI 设置 UI 重构探讨</h1>
|
||
<p style={{ color: 'var(--gn-muted)' }}>当前设计带有太多渐变和鲜艳色彩("AI 味")。以下是遵循 GoNavi 本身设计规范(克制、专业)的两个方案:</p>
|
||
</div>
|
||
<div className="prototype-container">
|
||
<V1ListDesign />
|
||
<V2CardDesign />
|
||
</div>
|
||
</ConfigProvider>
|
||
);
|
||
|
||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||
root.render(<App />);
|
||
</script>
|
||
</body>
|
||
</html>
|