优化APIClient和conversation-service优先使用rawContent提升上下文完整性;调整app-shell.js中对话气泡流式内容渲染逻辑及HTML模块特殊处理;提升STREAM_DEFAULT_OPTIONS maxTokens至30000;重构onepage-prompt.txt交付描述;大幅美化产品画布页面UI,采用Apple和Google风格边框、按钮、气泡,优化配色、阴影、交互效果和模态窗样式,提升整体视觉和交互体验。

This commit is contained in:
史悦
2025-11-19 11:28:44 +08:00
parent 24adda3f14
commit 19afa19462
5 changed files with 170 additions and 119 deletions

View File

@@ -14,61 +14,63 @@
font-family: 'Inter', sans-serif;
}
/* 狂野线条效果 */
.wild-border {
border: 3px solid;
box-shadow: 4px 4px 0px rgba(0,0,0,0.3);
/* Apple 风格边框 */
.apple-card {
border: 1px solid rgba(0,0,0,0.08);
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0,0,0,0.07), 0 1px 3px rgba(0,0,0,0.06);
backdrop-filter: blur(20px);
}
/* 切换按钮激活状态 */
/* 切换按钮激活状态 - Apple 风格 */
.mode-btn-active {
transform: translateY(-2px);
box-shadow: 0 4px 0 rgba(0,0,0,0.3);
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
transform: scale(1.02);
}
.mode-btn-inactive {
opacity: 0.6;
}
/* 对话气泡样式 */
/* 对话气泡样式 - Google 风格 */
.chat-bubble-user {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
background: #4C76AB;
color: white;
padding: 10px 14px;
padding: 12px 16px;
max-width: 80%;
border: 2px solid #000;
box-shadow: 2px 2px 0 rgba(0,0,0,0.2);
border-radius: 18px 18px 4px 18px;
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
}
.chat-bubble-ai {
background: #fff;
color: #1f2937;
padding: 10px 14px;
background: #f8f9fa;
color: #464646;
padding: 12px 16px;
max-width: 85%;
border: 2px solid #10b981;
box-shadow: 2px 2px 0 rgba(16, 185, 129, 0.3);
border-radius: 4px 18px 18px 18px;
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
}
/* SVG占位符样式 - 块级换行 + 新配色 */
/* SVG占位符样式 - Google 风格 */
.svg-placeholder-block {
display: block;
background: linear-gradient(135deg, #f59e0b 0%, #ef4444 100%);
background: #2B4269;
color: white;
padding: 8px 14px;
padding: 10px 16px;
margin: 8px 0;
border: 2px solid #000;
box-shadow: 3px 3px 0 rgba(0,0,0,0.25);
font-weight: bold;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1), 0 1px 2px rgba(0,0,0,0.06);
font-weight: 600;
font-size: 13px;
cursor: pointer;
transition: all 0.2s;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
text-align: center;
}
.svg-placeholder-block:hover {
transform: translateX(2px) translateY(-2px);
box-shadow: 4px 4px 0 rgba(0,0,0,0.3);
background: linear-gradient(135deg, #fb923c 0%, #f87171 100%);
box-shadow: 0 4px 8px rgba(0,0,0,0.16), 0 2px 4px rgba(0,0,0,0.08);
transform: translateY(-1px);
background: #5A6270;
}
/* 气泡操作按钮 */
@@ -113,28 +115,33 @@
}
.modal-content {
background: white;
border: 4px solid #000;
box-shadow: 8px 8px 0 rgba(0,0,0,0.4);
background: rgba(255,255,255,0.95);
border-radius: 20px;
box-shadow: 0 20px 25px -5px rgba(0,0,0,0.1),
0 10px 10px -5px rgba(0,0,0,0.04);
max-width: 500px;
width: 90%;
max-height: 90vh;
overflow-y: auto;
backdrop-filter: blur(20px);
border: 1px solid rgba(255,255,255,0.2);
}
/* 表单输入框样式 */
/* 表单输入框样式 - Google 风格 */
.config-input {
width: 100%;
padding: 10px;
border: 2px solid #000;
padding: 12px 16px;
border: 1px solid #dadce0;
border-radius: 4px;
font-size: 14px;
transition: all 0.2s;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
color: #464646;
}
.config-input:focus {
outline: none;
border-color: #667eea;
box-shadow: 3px 3px 0 rgba(102, 126, 234, 0.3);
border-color: #4C76AB;
box-shadow: 0 0 0 2px rgba(76, 118, 171, 0.1);
}
/* 齿轮旋转动画 */
@@ -148,31 +155,31 @@
}
</style>
</head>
<body class="bg-gray-100 h-screen flex flex-col">
<body class="bg-gray-50 h-screen flex flex-col" style="background: linear-gradient(180deg, #f8f9fa 0%, #ffffff 100%);">
<!-- 顶部标题栏 -->
<header class="bg-gradient-to-r from-orange-500 to-pink-500 p-3 flex items-center justify-between border-b-4 border-black">
<div class="flex items-center space-x-2">
<iconify-icon icon="ph:lightning-fill" class="text-3xl text-white"></iconify-icon>
<h1 id="page-title" class="text-2xl font-black text-white tracking-tight">产品画布</h1>
<header class="px-6 py-4 flex items-center justify-between" style="background: rgba(255,255,255,0.8); backdrop-filter: blur(20px); border-bottom: 1px solid rgba(0,0,0,0.06);">
<div class="flex items-center space-x-4">
<iconify-icon icon="ph:lightning-fill" class="text-3xl" style="color: #4C76AB;"></iconify-icon>
<h1 id="page-title" class="text-2xl font-semibold tracking-tight" style="color: #464646;">产品画布</h1>
</div>
<!-- 右侧按钮组 -->
<div class="flex items-center gap-3">
<div class="flex items-center gap-4">
<!-- API配置按钮 -->
<button id="settings-btn" class="settings-btn bg-white/20 text-white p-2 border-2 border-white hover:bg-white/30 transition-all" title="API配置">
<iconify-icon icon="ph:gear-six-fill" class="text-2xl"></iconify-icon>
<button id="settings-btn" class="settings-btn p-3 rounded-full hover:bg-gray-100 transition-all" style="color: #666666;" title="API配置">
<iconify-icon icon="ph:gear-six-fill" class="text-xl"></iconify-icon>
</button>
<span class="text-white font-bold text-sm">点击切换模式</span>
<iconify-icon icon="ph:hand-pointing-fill" class="text-2xl text-yellow-300 wave-hand"></iconify-icon>
<span class="font-medium text-sm" style="color: #888888;">点击切换模式</span>
<iconify-icon icon="ph:hand-pointing-fill" class="text-2xl wave-hand" style="color: #5A6270;"></iconify-icon>
<button id="canvas-mode-btn" class="mode-btn-active bg-white text-orange-600 px-4 py-2 font-bold border-2 border-black hover:bg-orange-50 transition-all duration-200">
<iconify-icon icon="ph:pen-nib-duotone" class="align-middle mr-1"></iconify-icon>
<button id="canvas-mode-btn" class="mode-btn-active px-5 py-2.5 font-medium rounded-full hover:bg-gray-100 transition-all duration-300" style="color: #464646; background: rgba(76,118,171,0.1);">
<iconify-icon icon="ph:pen-nib-duotone" class="align-middle mr-2"></iconify-icon>
产品画布
</button>
<button id="swot-mode-btn" class="mode-btn-inactive bg-white text-purple-600 px-4 py-2 font-bold border-2 border-black hover:bg-purple-50 transition-all duration-200">
<iconify-icon icon="ph:chart-bar-duotone" class="align-middle mr-1"></iconify-icon>
<button id="swot-mode-btn" class="mode-btn-inactive px-5 py-2.5 font-medium rounded-full hover:bg-gray-100 transition-all duration-300" style="color: #666666;">
<iconify-icon icon="ph:chart-bar-duotone" class="align-middle mr-2"></iconify-icon>
SWOT分析
</button>
</div>
@@ -182,7 +189,7 @@
<main class="flex-1 grid grid-cols-1 md:grid-cols-3 gap-4 p-4 overflow-hidden">
<!-- 左侧对话面板 -->
<div class="md:col-span-1 bg-white wild-border border-cyan-500 flex flex-col">
<div class="md:col-span-1 bg-white apple-card flex flex-col">
<!-- 对话历史区 -->
<div id="chat-history" class="flex-1 p-4 overflow-y-auto space-y-3">
@@ -253,40 +260,43 @@
</div>
<!-- 输入区 -->
<div class="p-3 border-t-3 border-gray-300 bg-yellow-50">
<div class="relative flex items-center gap-2">
<input
id="chat-input"
type="text"
placeholder="输入您的想法按Enter发送..."
class="flex-1 p-2 border-2 border-gray-800 focus:border-cyan-500 focus:outline-none transition-colors font-medium"
<div class="p-5 border-t bg-white" style="border-color: rgba(0,0,0,0.06);">
<div class="relative flex items-center gap-3">
<input
id="chat-input"
type="text"
placeholder="输入您的想法按Enter发送..."
class="flex-1 px-5 py-4 border focus:outline-none transition-all font-normal rounded-2xl"
style="border-color: rgba(0,0,0,0.08); color: #464646; background: rgba(248,249,250,0.8);"
onfocus="this.style.borderColor='#4C76AB'; this.style.boxShadow='0 0 0 3px rgba(76,118,171,0.15)'; this.style.background='rgba(255,255,255,0.95)'"
onblur="this.style.borderColor='rgba(0,0,0,0.08)'; this.style.boxShadow='none'; this.style.background='rgba(248,249,250,0.8)'"
/>
<button id="send-button" class="text-cyan-600 hover:text-cyan-700 transition-colors p-2 hover:scale-110 transform duration-200">
<iconify-icon icon="ph:paper-plane-tilt-fill" class="text-3xl"></iconify-icon>
<button id="send-button" class="p-3 rounded-full transition-all hover:scale-105" style="color: white; background: #4C76AB; box-shadow: 0 2px 8px rgba(76,118,171,0.3);" onmouseover="this.style.transform='scale(1.05)'" onmouseout="this.style.transform='scale(1)'">
<iconify-icon icon="ph:paper-plane-tilt-fill" class="text-xl"></iconify-icon>
</button>
</div>
</div>
</div>
<!-- 右侧显示面板 -->
<div class="md:col-span-2 bg-white wild-border border-purple-600 flex flex-col">
<div id="svg-viewer" class="flex-1 flex items-center justify-center p-4 bg-gradient-to-br from-purple-50 to-pink-50 overflow-auto">
<div id="svg-placeholder" class="text-center text-gray-400">
<iconify-icon icon="ph:image-square" class="text-6xl mx-auto text-purple-400"></iconify-icon>
<div class="md:col-span-2 bg-white apple-card flex flex-col">
<div id="svg-viewer" class="flex-1 flex items-center justify-center p-8 overflow-auto" style="background: linear-gradient(135deg, #fafafa 0%, #f8f9fa 100%);">
<div id="svg-placeholder" class="text-center" style="color: #787878;">
<iconify-icon icon="ph:image-square" class="text-6xl mx-auto" style="color: #5586F5;"></iconify-icon>
<p class="mt-2 font-bold" id="placeholder-text">生成的产品画布将在此处显示</p>
</div>
</div>
<!-- 底部操作栏 -->
<div class="p-3 border-t-3 border-gray-300 flex justify-end items-center gap-2 bg-gray-800">
<button id="download-svg-btn" class="p-2 bg-orange-500 text-white border-2 border-black hover:bg-orange-600 transition-all" title="下载SVG">
<iconify-icon icon="mdi:download-outline" class="text-xl"></iconify-icon>
<div class="p-5 border-t flex justify-end items-center gap-4" style="border-color: rgba(0,0,0,0.06); background: rgba(248,249,250,0.8);">
<button id="download-svg-btn" class="p-3 text-white rounded-xl transition-all" style="background: #5A6270; box-shadow: 0 4px 12px rgba(90,98,112,0.25);" title="下载SVG" onmouseover="this.style.transform='translateY(-2px)'" onmouseout="this.style.transform='translateY(0)'">
<iconify-icon icon="mdi:download-outline" class="text-lg"></iconify-icon>
</button>
<button id="export-image-btn" class="p-2 bg-green-500 text-white border-2 border-black hover:bg-green-600 transition-all" title="导出为图片">
<iconify-icon icon="mdi:image-outline" class="text-xl"></iconify-icon>
<button id="export-image-btn" class="p-3 text-white rounded-xl transition-all" style="background: #2B4269; box-shadow: 0 4px 12px rgba(43,66,105,0.25);" title="导出为图片" onmouseover="this.style.transform='translateY(-2px)'" onmouseout="this.style.transform='translateY(0)'">
<iconify-icon icon="mdi:image-outline" class="text-lg"></iconify-icon>
</button>
<button id="view-code-btn" class="p-2 bg-blue-500 text-white border-2 border-black hover:bg-blue-600 transition-all" title="查看代码">
<iconify-icon icon="mdi:code-tags" class="text-xl"></iconify-icon>
<button id="view-code-btn" class="p-3 text-white rounded-xl transition-all" style="background: #4C76AB; box-shadow: 0 4px 12px rgba(76,118,171,0.25);" title="查看代码" onmouseover="this.style.transform='translateY(-2px)'" onmouseout="this.style.transform='translateY(0)'">
<iconify-icon icon="mdi:code-tags" class="text-lg"></iconify-icon>
</button>
</div>
</div>
@@ -297,13 +307,13 @@
<div id="config-modal" class="modal-overlay">
<div class="modal-content">
<!-- 模态窗头部 -->
<div class="bg-gradient-to-r from-blue-600 to-purple-600 p-4 border-b-4 border-black flex items-center justify-between">
<div class="flex items-center gap-2">
<iconify-icon icon="ph:plugs-connected-fill" class="text-3xl text-white"></iconify-icon>
<h2 class="text-xl font-black text-white">API 配置</h2>
<div class="p-6 border-b flex items-center justify-between" style="background: rgba(255,255,255,0.95); border-color: rgba(0,0,0,0.06); border-radius: 20px 20px 0 0;">
<div class="flex items-center gap-4">
<iconify-icon icon="ph:plugs-connected-fill" class="text-2xl" style="color: #4C76AB;"></iconify-icon>
<h2 class="text-xl font-semibold" style="color: #464646;">API 配置</h2>
</div>
<button id="close-modal-btn" class="text-white hover:bg-white/20 p-2 transition-all">
<iconify-icon icon="ph:x-bold" class="text-2xl"></iconify-icon>
<button id="close-modal-btn" class="hover:bg-gray-100 p-3 rounded-full transition-all" style="color: #666666;" onmouseover="this.style.backgroundColor='#f0f0f0'" onmouseout="this.style.backgroundColor='transparent'">
<iconify-icon icon="ph:x-bold" class="text-xl"></iconify-icon>
</button>
</div>
@@ -311,14 +321,14 @@
<div class="p-6 space-y-4">
<!-- API URL -->
<div>
<label class="block font-bold text-gray-800 mb-2 flex items-center gap-2">
<iconify-icon icon="ph:link-bold" class="text-lg text-blue-600"></iconify-icon>
<label class="block font-semibold mb-3 flex items-center gap-3" style="color: #464646;">
<iconify-icon icon="ph:link-bold" class="text-lg" style="color: #4C76AB;"></iconify-icon>
API URL
</label>
<input
id="api-url"
type="text"
placeholder="https://api.example.com/v1/chat"
<input
id="api-url"
type="text"
placeholder="https://api.example.com/v1/chat"
class="config-input"
value=""
/>
@@ -326,14 +336,14 @@
<!-- API Key -->
<div>
<label class="block font-bold text-gray-800 mb-2 flex items-center gap-2">
<iconify-icon icon="ph:key-bold" class="text-lg text-green-600"></iconify-icon>
<label class="block font-semibold mb-3 flex items-center gap-3" style="color: #464646;">
<iconify-icon icon="ph:key-bold" class="text-lg" style="color: #2B4269;"></iconify-icon>
API Key
</label>
<input
id="api-key"
type="password"
placeholder="sk-xxxxxxxxxxxxxxxx"
<input
id="api-key"
type="password"
placeholder="sk-xxxxxxxxxxxxxxxx"
class="config-input"
value=""
/>
@@ -341,33 +351,33 @@
<!-- Model -->
<div>
<label class="block font-bold text-gray-800 mb-2 flex items-center gap-2">
<iconify-icon icon="ph:robot-bold" class="text-lg text-purple-600"></iconify-icon>
<label class="block font-semibold mb-3 flex items-center gap-3" style="color: #464646;">
<iconify-icon icon="ph:robot-bold" class="text-lg" style="color: #5A6270;"></iconify-icon>
模型 (Model)
</label>
<input
id="api-model"
type="text"
placeholder="gpt-4-turbo"
<input
id="api-model"
type="text"
placeholder="gpt-4-turbo"
class="config-input"
value=""
/>
</div>
<!-- 状态显示 -->
<div id="config-status" class="p-3 border-2 border-gray-300 bg-gray-50 text-sm text-gray-600 hidden">
<div id="config-status" class="p-4 border rounded-2xl bg-gray-50 text-sm hidden" style="border-color: rgba(0,0,0,0.06); color: #888888;">
<iconify-icon icon="ph:info" class="align-middle"></iconify-icon>
<span id="status-text">等待操作...</span>
</div>
</div>
<!-- 模态窗底部按钮 -->
<div class="p-4 border-t-3 border-gray-300 bg-gray-100 flex gap-3 justify-end">
<button id="test-api-btn" class="px-4 py-2 bg-yellow-500 text-white font-bold border-2 border-black hover:bg-yellow-600 transition-all flex items-center gap-2">
<div class="p-6 border-t bg-white flex gap-4 justify-end" style="border-color: rgba(0,0,0,0.06); border-radius: 0 0 20px 20px;">
<button id="test-api-btn" class="px-6 py-3 text-white font-medium rounded-2xl transition-all flex items-center gap-3" style="background: #5A6270; box-shadow: 0 4px 12px rgba(90,98,112,0.25);" onmouseover="this.style.transform='translateY(-2px)'" onmouseout="this.style.transform='translateY(0)'">
<iconify-icon icon="ph:flask-bold"></iconify-icon>
测试连接
</button>
<button id="save-config-btn" class="px-4 py-2 bg-green-500 text-white font-bold border-2 border-black hover:bg-green-600 transition-all flex items-center gap-2">
<button id="save-config-btn" class="px-6 py-3 text-white font-medium rounded-2xl transition-all flex items-center gap-3" style="background: #4C76AB; box-shadow: 0 4px 12px rgba(76,118,171,0.25);" onmouseover="this.style.transform='translateY(-2px)'" onmouseout="this.style.transform='translateY(0)'">
<iconify-icon icon="ph:floppy-disk-bold"></iconify-icon>
保存配置
</button>
@@ -505,19 +515,22 @@
configStatus.classList.remove('hidden');
statusText.textContent = message;
configStatus.classList.remove('border-gray-300', 'bg-gray-50', 'text-gray-600');
configStatus.classList.remove('border-green-500', 'bg-green-50', 'text-green-700');
configStatus.classList.remove('border-red-500', 'bg-red-50', 'text-red-700');
configStatus.classList.remove('border-blue-500', 'bg-blue-50', 'text-blue-700');
configStatus.style.borderColor = '#787878';
configStatus.style.backgroundColor = '#f9fafb';
configStatus.style.color = '#787878';
if (type === 'success') {
configStatus.classList.add('border-green-500', 'bg-green-50', 'text-green-700');
configStatus.style.borderColor = '#47A74F';
configStatus.style.backgroundColor = '#e8f5e9';
configStatus.style.color = '#2e7d32';
} else if (type === 'error') {
configStatus.classList.add('border-red-500', 'bg-red-50', 'text-red-700');
configStatus.style.borderColor = '#E04639';
configStatus.style.backgroundColor = '#ffebee';
configStatus.style.color = '#c62828';
} else if (type === 'loading') {
configStatus.classList.add('border-blue-500', 'bg-blue-50', 'text-blue-700');
} else {
configStatus.classList.add('border-gray-300', 'bg-gray-50', 'text-gray-600');
configStatus.style.borderColor = '#5586F5';
configStatus.style.backgroundColor = '#e3f2fd';
configStatus.style.color = '#1565c0';
}
}