Skip to content

Commit 2e8559f

Browse files
author
chaoyuepan
committed
improve ui
1 parent 2e50e2c commit 2e8559f

10 files changed

Lines changed: 560 additions & 58 deletions

File tree

.baidu-cc/meta.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"session_id": "5eb0d198-0331-459a-97a0-62918bc69861",
3+
"transcript_path": "/Users/chaoyuepan/.claude/projects/-Users-chaoyuepan-ai-notex/5eb0d198-0331-459a-97a0-62918bc69861.jsonl",
4+
"cwd": "/Users/chaoyuepan/ai/notex"
5+
}

backend/agent.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,24 @@ func NewAgent(cfg Config, vectorStore *VectorStore) (*Agent, error) {
3030
return nil, fmt.Errorf("failed to create LLM: %w", err)
3131
}
3232

33-
provider := NewGeminiClient(cfg.GoogleAPIKey, llm)
33+
// Select image provider based on config
34+
var provider LLMProvider
35+
switch cfg.ImageProvider {
36+
case "glm":
37+
if cfg.GLMAPIKey == "" {
38+
return nil, fmt.Errorf("glm_api_key is required when image_provider is 'glm'")
39+
}
40+
provider = NewGLMImageClient(cfg.GLMAPIKey)
41+
case "zimage":
42+
if cfg.ZImageAPIKey == "" {
43+
return nil, fmt.Errorf("zimage_api_key is required when image_provider is 'zimage'")
44+
}
45+
provider = NewZImageClient(cfg.ZImageAPIKey)
46+
case "gemini":
47+
provider = NewGeminiClient(cfg.GoogleAPIKey, llm)
48+
default:
49+
return nil, fmt.Errorf("unknown image provider: %s (supported: gemini, glm, zimage)", cfg.ImageProvider)
50+
}
3451

3552
return &Agent{
3653
vectorStore: vectorStore,

backend/config.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ type Config struct {
2323
OllamaBaseURL string
2424
OllamaModel string
2525

26+
// Image generation settings
27+
ImageProvider string // "gemini", "glm", "zimage"
28+
GLMAPIKey string
29+
GLMImageModel string
30+
GeminiImageModel string
31+
ZImageAPIKey string
32+
ZImageModel string
33+
2634
// Vector store settings
2735
VectorStoreType string // "memory", "supabase", "pgvector", "redis", "sqlite"
2836
SupabaseURL string
@@ -93,6 +101,12 @@ func LoadConfig() Config {
93101
GoogleAPIKey: getEnv("GOOGLE_API_KEY", ""),
94102
OllamaBaseURL: getEnv("OLLAMA_BASE_URL", "http://localhost:11434"),
95103
OllamaModel: getEnv("OLLAMA_MODEL", "llama3.2"),
104+
ImageProvider: getEnv("IMAGE_PROVIDER", "gemini"),
105+
GLMAPIKey: getEnv("GLM_API_KEY", ""),
106+
GLMImageModel: getEnv("GLM_IMAGE_MODEL", "glm-image"),
107+
GeminiImageModel: getEnv("GEMINI_IMAGE_MODEL", "gemini-2.0-flash-exp"),
108+
ZImageAPIKey: getEnv("ZIMAGE_API_KEY", ""),
109+
ZImageModel: getEnv("ZIMAGE_MODEL", "z-image-turbo"),
96110
VectorStoreType: getEnv("VECTOR_STORE_TYPE", "sqlite"),
97111
SupabaseURL: getEnv("SUPABASE_URL", ""),
98112
SupabaseKey: getEnv("SUPABASE_KEY", ""),

backend/frontend/static/app.js

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,9 @@ class OpenNotebook {
749749
// Also remove token cookie
750750
document.cookie = 'token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT';
751751

752+
// Clear cache
753+
this.cache.delete('notebooks');
754+
752755
this.updateAuthUI();
753756

754757
// Clear data
@@ -759,6 +762,9 @@ class OpenNotebook {
759762

760763
// 笔记本方法
761764
async loadNotebooks() {
765+
// Always load public notebooks showcase (regardless of private notebooks)
766+
await this.loadPublicNotebooksShowcase();
767+
762768
try {
763769
// 先尝试从缓存获取
764770
const cached = this.cache.get('notebooks');
@@ -778,7 +784,12 @@ class OpenNotebook {
778784
this.renderNotebooks();
779785
this.updateFooter();
780786
} catch (error) {
781-
this.showError('加载笔记本失败');
787+
// 401 Unauthorized is expected for non-logged-in users, don't show error
788+
if (error.message && !error.message.includes('401')) {
789+
console.warn('用户未登录,跳过私有笔记本加载');
790+
} else {
791+
this.showError('加载笔记本失败');
792+
}
782793
}
783794
}
784795

@@ -859,6 +870,10 @@ class OpenNotebook {
859870

860871
// Load and render public notebooks showcase
861872
async loadPublicNotebooksShowcase() {
873+
// Prevent duplicate calls
874+
if (this._publicNotebooksLoaded) return;
875+
this._publicNotebooksLoaded = true;
876+
862877
try {
863878
const response = await fetch('/public/notebooks');
864879
if (!response.ok) return;
@@ -870,6 +885,9 @@ class OpenNotebook {
870885
}
871886
}
872887

888+
// Cache to avoid duplicate calls
889+
_publicNotebooksLoaded = false;
890+
873891
renderPublicNotebooksShowcase(notebooks) {
874892
const container = document.getElementById('publicShowcase');
875893
const grid = document.getElementById('publicShowcaseGrid');
@@ -890,25 +908,17 @@ class OpenNotebook {
890908
card.className = 'public-showcase-card';
891909
card.href = `/public/${nb.public_token}`;
892910

911+
// Generate background style if cover image exists
912+
if (nb.cover_image_url) {
913+
card.style.backgroundImage = `url('${nb.cover_image_url}')`;
914+
card.style.backgroundSize = 'cover';
915+
card.style.backgroundPosition = 'center';
916+
card.classList.add('has-cover-image');
917+
}
918+
893919
card.innerHTML = `
894-
<div class="public-showcase-card-header">
895-
<div class="public-showcase-card-icon">
896-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
897-
<rect x="3" y="3" width="18" height="18" rx="2"/>
898-
<path d="M3 9h18"/>
899-
<path d="M9 21V9"/>
900-
</svg>
901-
</div>
902-
<div>
903-
<h3 class="public-showcase-card-title">${this.escapeHtml(nb.name)}</h3>
904-
</div>
905-
</div>
906-
<p class="public-showcase-card-desc">${this.escapeHtml(nb.description || '暂无描述')}</p>
907-
<div class="public-showcase-card-footer">
908-
<div class="public-showcase-card-stats">
909-
<span>${nb.source_count || 0} 来源</span>
910-
<span>${nb.note_count || 0} 笔记</span>
911-
</div>
920+
<div class="public-showcase-card-content">
921+
<h3 class="public-showcase-card-title">${this.escapeHtml(nb.name)}</h3>
912922
</div>
913923
`;
914924

backend/frontend/static/style.css

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2619,6 +2619,31 @@ body {
26192619
box-shadow: var(--shadow-md);
26202620
text-decoration: none;
26212621
color: inherit;
2622+
overflow: hidden;
2623+
position: relative;
2624+
}
2625+
2626+
.public-showcase-card.has-cover-image {
2627+
background-size: cover !important;
2628+
background-position: center !important;
2629+
background-repeat: no-repeat;
2630+
}
2631+
2632+
.public-showcase-card.has-cover-image::before {
2633+
content: '';
2634+
position: absolute;
2635+
inset: 0;
2636+
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.85));
2637+
pointer-events: none;
2638+
z-index: 1;
2639+
}
2640+
2641+
.public-showcase-card-content {
2642+
position: relative;
2643+
z-index: 2;
2644+
display: flex;
2645+
flex-direction: column;
2646+
height: 100%;
26222647
}
26232648

26242649
.public-showcase-card:hover {
@@ -2627,55 +2652,52 @@ body {
26272652
border-color: var(--accent-primary);
26282653
}
26292654

2655+
/* Text styles for cards with cover image */
2656+
.public-showcase-card.has-cover-image .public-showcase-card-title,
2657+
.public-showcase-card.has-cover-image .public-showcase-card-desc,
2658+
.public-showcase-card.has-cover-image .public-showcase-card-footer,
2659+
.public-showcase-card.has-cover-image .public-showcase-card-stats {
2660+
color: white;
2661+
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
2662+
}
2663+
2664+
.public-showcase-card.has-cover-image .public-showcase-card-icon {
2665+
background: rgba(255, 255, 255, 0.25);
2666+
color: white;
2667+
}
2668+
26302669
.public-showcase-card-header {
2631-
display: flex;
2632-
align-items: flex-start;
2633-
gap: var(--space-md);
2634-
margin-bottom: var(--space-md);
2670+
display: none;
26352671
}
26362672

26372673
.public-showcase-card-icon {
2638-
width: 40px;
2639-
height: 40px;
2640-
color: #10b981;
2641-
background: rgba(16, 185, 129, 0.1);
2642-
border-radius: var(--radius-lg);
2643-
padding: var(--space-sm);
2644-
flex-shrink: 0;
2674+
display: none;
26452675
}
26462676

26472677
.public-showcase-card-title {
2648-
font-size: 1rem;
2678+
font-size: 1.25rem;
26492679
font-weight: 600;
26502680
color: var(--text-primary);
2651-
margin-bottom: var(--space-xs);
2652-
line-height: 1.4;
2681+
margin: 0;
2682+
text-align: center;
2683+
}
2684+
2685+
/* Text styles for cards with cover image */
2686+
.public-showcase-card.has-cover-image .public-showcase-card-title {
2687+
color: white;
2688+
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
26532689
}
26542690

26552691
.public-showcase-card-desc {
2656-
font-size: 0.875rem;
2657-
color: var(--text-muted);
2658-
line-height: 1.5;
2659-
display: -webkit-box;
2660-
-webkit-line-clamp: 2;
2661-
-webkit-box-orient: vertical;
2662-
overflow: hidden;
2663-
flex: 1;
2692+
display: none;
26642693
}
26652694

26662695
.public-showcase-card-footer {
2667-
display: flex;
2668-
justify-content: space-between;
2669-
align-items: center;
2670-
padding-top: var(--space-md);
2671-
border-top: 1px solid var(--border-color);
2672-
font-size: 0.75rem;
2673-
color: var(--text-muted);
2696+
display: none;
26742697
}
26752698

26762699
.public-showcase-card-stats {
2677-
display: flex;
2678-
gap: var(--space-md);
2700+
display: none;
26792701
}
26802702

26812703
.notebook-grid {

0 commit comments

Comments
 (0)