Skip to content

Commit 9c0771b

Browse files
lusaltiaclaude
andcommitted
feat: rebrand to AppPulse with refined Notion-style UI
- Rename Review Radar → AppPulse with slogan "感知每一条用户心声" - Apply blue-purple gradient (#4F46E5 → #7C3AED) as brand accent color - Upgrade CSS: gradient title text, gradient buttons with hover effects, metric cards with rounded corners and background, sidebar styling, outlined download buttons, refined step indicators - Unify all chart colors to brand palette - Update HTML report template branding and colors Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 91a64c8 commit 9c0771b

3 files changed

Lines changed: 92 additions & 57 deletions

File tree

.streamlit/config.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ maxMessageSize = 200
1111
gatherUsageStats = false
1212

1313
[theme]
14-
primaryColor = "#37352F"
14+
primaryColor = "#4F46E5"
1515
backgroundColor = "#FFFFFF"
16-
secondaryBackgroundColor = "#F7F6F3"
17-
textColor = "#37352F"
16+
secondaryBackgroundColor = "#F8F7FF"
17+
textColor = "#1E1E2E"
18+
font = "sans serif"

review_radar/report.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -108,21 +108,21 @@ def _save_code(m):
108108
max-width: 800px;
109109
margin: 0 auto;
110110
padding: 40px 20px;
111-
color: #37352F;
111+
color: #1E1E2E;
112112
background: #FFFFFF;
113113
line-height: 1.7;
114114
}}
115-
h1 {{ font-size: 2em; font-weight: 700; margin-top: 2em; border-bottom: 2px solid #E8E8E8; padding-bottom: 8px; }}
116-
h2 {{ font-size: 1.5em; font-weight: 600; margin-top: 1.8em; border-bottom: 1px solid #E8E8E8; padding-bottom: 6px; }}
115+
h1 {{ font-size: 2em; font-weight: 700; margin-top: 2em; border-bottom: 2px solid #E5E7EB; padding-bottom: 8px; }}
116+
h2 {{ font-size: 1.5em; font-weight: 600; margin-top: 1.8em; border-bottom: 1px solid #E5E7EB; padding-bottom: 6px; }}
117117
h3 {{ font-size: 1.25em; font-weight: 600; margin-top: 1.5em; }}
118118
h4 {{ font-size: 1.1em; font-weight: 600; margin-top: 1.2em; }}
119119
p {{ margin: 0.8em 0; }}
120120
blockquote {{
121-
border-left: 3px solid #E8E8E8;
121+
border-left: 3px solid #E5E7EB;
122122
padding: 4px 16px;
123123
margin: 12px 0;
124-
color: #787774;
125-
background: #F7F6F3;
124+
color: #6B7280;
125+
background: #F8F7FF;
126126
border-radius: 0 4px 4px 0;
127127
}}
128128
table {{
@@ -132,19 +132,19 @@ def _save_code(m):
132132
font-size: 0.9em;
133133
}}
134134
th, td {{
135-
border: 1px solid #E8E8E8;
135+
border: 1px solid #E5E7EB;
136136
padding: 8px 12px;
137137
text-align: left;
138138
}}
139139
th {{
140-
background: #F7F6F3;
140+
background: #F8F7FF;
141141
font-weight: 600;
142142
}}
143143
tr:nth-child(even) {{ background: #FAFAFA; }}
144-
hr {{ border: none; border-top: 1px solid #E8E8E8; margin: 2em 0; }}
144+
hr {{ border: none; border-top: 1px solid #E5E7EB; margin: 2em 0; }}
145145
strong {{ font-weight: 600; }}
146146
pre {{
147-
background: #F7F6F3;
147+
background: #F8F7FF;
148148
padding: 12px 16px;
149149
border-radius: 4px;
150150
overflow-x: auto;
@@ -154,8 +154,8 @@ def _save_code(m):
154154
.footer {{
155155
margin-top: 3em;
156156
padding-top: 1em;
157-
border-top: 1px solid #E8E8E8;
158-
color: #787774;
157+
border-top: 1px solid #E5E7EB;
158+
color: #6B7280;
159159
font-size: 0.85em;
160160
text-align: center;
161161
}}
@@ -164,7 +164,7 @@ def _save_code(m):
164164
<body>
165165
{content}
166166
<div class="footer">
167-
Generated by Review Radar &middot; {date}
167+
Generated by AppPulse &middot; {date}
168168
</div>
169169
</body>
170170
</html>"""

web/app.py

Lines changed: 75 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Review Radar — Streamlit Web UI v2(4 步引导交互)"""
1+
"""AppPulse — Streamlit Web UI v2(4 步引导交互)"""
22

33
import streamlit as st
44
import plotly.graph_objects as go
@@ -53,37 +53,66 @@ def _load_cache(key: str) -> dict | None:
5353
return None
5454

5555
# ── 页面配置 ──
56-
st.set_page_config(page_title="Review Radar", page_icon="📡", layout="centered")
56+
st.set_page_config(page_title="AppPulse", page_icon="📊", layout="centered")
5757

58-
# ── Notion 风格 CSS ──
58+
# ── AppPulse 品牌 CSS ──
5959
st.markdown("""
6060
<style>
61-
.stApp { background-color: #FFFFFF; color: #37352F; }
62-
.main-title { font-size: 42px; font-weight: 700; color: #37352F; margin-bottom: 4px; letter-spacing: -0.5px; }
63-
.sub-title { font-size: 18px; color: #787774; margin-bottom: 32px; font-weight: 400; }
64-
.section-title { font-size: 24px; font-weight: 600; color: #37352F; margin-top: 36px; margin-bottom: 16px; padding-bottom: 8px; border-bottom: 1px solid #E8E8E8; }
65-
.step-title { font-size: 20px; font-weight: 600; color: #37352F; margin-bottom: 12px; }
66-
.step-desc { font-size: 15px; color: #787774; margin-bottom: 20px; }
67-
.metric-card { padding: 24px 0; text-align: center; }
68-
.metric-value { font-size: 36px; font-weight: 700; color: #37352F; line-height: 1.2; }
69-
.metric-label { font-size: 14px; color: #787774; margin-top: 4px; }
70-
.app-card { display: flex; align-items: center; gap: 16px; padding: 20px; border: 1px solid #E8E8E8; border-radius: 8px; margin: 16px 0; }
61+
.stApp { background-color: #FFFFFF; color: #1E1E2E; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans SC", sans-serif; }
62+
.main-title {
63+
font-size: 40px; font-weight: 800; letter-spacing: -0.5px; margin-bottom: 2px;
64+
background: linear-gradient(135deg, #4F46E5, #7C3AED);
65+
-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
66+
}
67+
.sub-title { font-size: 16px; color: #6B7280; margin-bottom: 36px; font-weight: 400; letter-spacing: 0.3px; }
68+
.section-title { font-size: 22px; font-weight: 700; color: #1E1E2E; margin-top: 40px; margin-bottom: 18px; padding-bottom: 10px; border-bottom: 2px solid #E5E7EB; }
69+
.step-title { font-size: 20px; font-weight: 700; color: #1E1E2E; margin-bottom: 10px; }
70+
.step-desc { font-size: 14px; color: #6B7280; margin-bottom: 22px; line-height: 1.6; }
71+
.metric-card { padding: 20px 16px; text-align: center; background: #F8F7FF; border-radius: 12px; border: 1px solid #E5E7EB; }
72+
.metric-value { font-size: 32px; font-weight: 800; color: #4F46E5; line-height: 1.2; }
73+
.metric-label { font-size: 13px; color: #6B7280; margin-top: 6px; font-weight: 500; }
74+
.app-card {
75+
display: flex; align-items: center; gap: 16px; padding: 20px 24px;
76+
border: 1px solid #E5E7EB; border-radius: 12px; margin: 16px 0; background: #FFFFFF;
77+
box-shadow: 0 1px 3px rgba(0,0,0,0.04), 0 1px 2px rgba(0,0,0,0.06);
78+
transition: box-shadow 0.2s ease;
79+
}
80+
.app-card:hover { box-shadow: 0 4px 12px rgba(79,70,229,0.08); }
7181
.app-icon { width: 64px; height: 64px; border-radius: 14px; }
7282
.app-info { flex: 1; }
73-
.app-name { font-size: 20px; font-weight: 600; color: #37352F; }
74-
.app-category { font-size: 14px; color: #787774; }
83+
.app-name { font-size: 20px; font-weight: 700; color: #1E1E2E; }
84+
.app-category { font-size: 14px; color: #6B7280; }
7585
.country-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin: 12px 0; }
76-
.country-item { padding: 8px 12px; border-radius: 6px; font-size: 14px; }
77-
.country-ok { background: #F0FFF0; color: #2E7D32; }
78-
.country-no { background: #FFF0F0; color: #C62828; text-decoration: line-through; }
79-
.phase-item { padding: 6px 0; font-size: 15px; color: #37352F; }
80-
.phase-done { color: #787774; }
86+
.country-item { padding: 8px 12px; font-size: 14px; }
87+
.country-ok { background: #F0FDF4; color: #166534; border: 1px solid #BBF7D0; border-radius: 8px; }
88+
.country-no { background: #FEF2F2; color: #991B1B; text-decoration: line-through; border: 1px solid #FECACA; border-radius: 8px; }
89+
.phase-item { padding: 6px 0; font-size: 15px; color: #1E1E2E; }
90+
.phase-done { color: #6B7280; }
8191
.phase-active { font-weight: 600; }
8292
#MainMenu {visibility: hidden;} footer {visibility: hidden;}
8393
header [data-testid="stHeader"] {visibility: visible !important;}
8494
button[kind="header"] {visibility: visible !important;}
85-
.stButton > button { background-color: #37352F; color: white; border: none; padding: 12px 32px; font-size: 16px; border-radius: 4px; font-weight: 500; }
86-
.stButton > button:hover { background-color: #555555; }
95+
.stButton > button {
96+
background: linear-gradient(135deg, #4F46E5, #7C3AED); color: white;
97+
border: none; padding: 10px 28px; font-size: 15px; border-radius: 8px; font-weight: 600;
98+
transition: all 0.2s ease; box-shadow: 0 1px 3px rgba(79,70,229,0.3);
99+
}
100+
.stButton > button:hover {
101+
background: linear-gradient(135deg, #4338CA, #6D28D9);
102+
box-shadow: 0 4px 12px rgba(79,70,229,0.35); transform: translateY(-1px);
103+
}
104+
.stButton > button:active { transform: translateY(0); }
105+
section[data-testid="stSidebar"] { background-color: #FAFAFE; border-right: 1px solid #E5E7EB; }
106+
section[data-testid="stSidebar"] .stMarkdown h3 { font-size: 15px; font-weight: 700; color: #1E1E2E; letter-spacing: 0.02em; }
107+
hr { border: none; border-top: 1px solid #E5E7EB; margin: 24px 0; }
108+
.stTabs [data-baseweb="tab-list"] { gap: 8px; }
109+
.stTabs [data-baseweb="tab"] { border-radius: 8px 8px 0 0; font-weight: 600; font-size: 14px; }
110+
.stDownloadButton > button {
111+
background: #FFFFFF !important; color: #4F46E5 !important;
112+
border: 1px solid #4F46E5 !important; border-radius: 8px; font-weight: 600;
113+
}
114+
.stDownloadButton > button:hover { background: #F8F7FF !important; }
115+
.streamlit-expanderHeader { font-weight: 600; font-size: 14px; }
87116
</style>
88117
""", unsafe_allow_html=True)
89118

@@ -242,20 +271,20 @@ def _load_cache(key: str) -> dict | None:
242271
st.caption("暂无历史记录")
243272

244273
# ── 标题 ──
245-
st.markdown('<div class="main-title">Review Radar</div>', unsafe_allow_html=True)
246-
st.markdown('<div class="sub-title">输入 App 名字,自动分析用户评论,生成洞察报告</div>', unsafe_allow_html=True)
274+
st.markdown('<div class="main-title">AppPulse</div>', unsafe_allow_html=True)
275+
st.markdown('<div class="sub-title">感知每一条用户心声</div>', unsafe_allow_html=True)
247276

248277
# ── 步骤指示器 ──
249278
step = st.session_state.step
250279
steps = ["搜索 App", "选择市场与国家", "高级选项", "分析"]
251280
cols = st.columns(len(steps))
252281
for i, (col, label) in enumerate(zip(cols, steps), 1):
253282
if i < step:
254-
col.markdown(f"<div style='text-align:center;color:#787774;'>✓ {label}</div>", unsafe_allow_html=True)
283+
col.markdown(f"<div style='text-align:center;color:#10B981;font-weight:600;font-size:14px;'>✓ {label}</div>", unsafe_allow_html=True)
255284
elif i == step:
256-
col.markdown(f"<div style='text-align:center;font-weight:600;color:#37352F;'>● {label}</div>", unsafe_allow_html=True)
285+
col.markdown(f"<div style='text-align:center;font-weight:700;color:#4F46E5;font-size:14px;padding:4px 0;border-bottom:2px solid #4F46E5;'>● {label}</div>", unsafe_allow_html=True)
257286
else:
258-
col.markdown(f"<div style='text-align:center;color:#CFCFCF;'>○ {label}</div>", unsafe_allow_html=True)
287+
col.markdown(f"<div style='text-align:center;color:#D1D5DB;font-size:14px;'>○ {label}</div>", unsafe_allow_html=True)
259288

260289
st.markdown("---")
261290

@@ -265,7 +294,7 @@ def _load_cache(key: str) -> dict | None:
265294
# ════════════════════════════════════════════════════════════════
266295
def _render_sentiment_pie(sentiment: dict, title: str):
267296
"""情感分布饼图"""
268-
colors_map = {"positive": "#4285F4", "negative": "#EA8600", "neutral": "#9AA0A6"}
297+
colors_map = {"positive": "#4F46E5", "negative": "#F59E0B", "neutral": "#D1D5DB"}
269298
labels_cn = {"positive": "正面", "negative": "负面", "neutral": "中性"}
270299
fig = go.Figure(data=[go.Pie(
271300
labels=[labels_cn.get(k, k) for k in sentiment.keys()],
@@ -274,7 +303,8 @@ def _render_sentiment_pie(sentiment: dict, title: str):
274303
hole=0.45, textinfo="label+percent", textfont=dict(size=14),
275304
)])
276305
fig.update_layout(showlegend=False, margin=dict(t=20, b=20, l=20, r=20), height=280,
277-
paper_bgcolor="rgba(0,0,0,0)", plot_bgcolor="rgba(0,0,0,0)")
306+
paper_bgcolor="rgba(0,0,0,0)", plot_bgcolor="rgba(0,0,0,0)",
307+
font=dict(family="-apple-system, BlinkMacSystemFont, Segoe UI, sans-serif", color="#1E1E2E"))
278308
st.plotly_chart(fig, use_container_width=True)
279309

280310

@@ -283,18 +313,19 @@ def _render_category_bar(categories: dict, title: str):
283313
sorted_cats = sorted(categories.items(), key=lambda x: x[1], reverse=True)
284314
fig2 = go.Figure(data=[go.Bar(
285315
x=[c[1] for c in sorted_cats], y=[c[0] for c in sorted_cats],
286-
orientation='h', marker_color="#37352F",
316+
orientation='h', marker_color="#4F46E5",
287317
)])
288318
fig2.update_layout(margin=dict(t=20, b=20, l=20, r=20), height=280,
289319
paper_bgcolor="rgba(0,0,0,0)", plot_bgcolor="rgba(0,0,0,0)",
290-
xaxis=dict(showgrid=False), yaxis=dict(showgrid=False, autorange="reversed"))
320+
xaxis=dict(showgrid=False), yaxis=dict(showgrid=False, autorange="reversed"),
321+
font=dict(family="-apple-system, BlinkMacSystemFont, Segoe UI, sans-serif", color="#1E1E2E"))
291322
st.plotly_chart(fig2, use_container_width=True)
292323

293324

294325
def _render_rating_dist(rating_dist: dict, title: str):
295326
"""评分分布柱状图"""
296327
stars = sorted(rating_dist.keys(), key=lambda x: int(x))
297-
colors_rating = {1: "#D93025", 2: "#EA8600", 3: "#F9AB00", 4: "#5BB974", 5: "#4285F4"}
328+
colors_rating = {1: "#EF4444", 2: "#F59E0B", 3: "#FBBF24", 4: "#34D399", 5: "#4F46E5"}
298329
fig3 = go.Figure(data=[go.Bar(
299330
x=[f"{s} 星" for s in stars],
300331
y=[rating_dist[s] for s in stars],
@@ -304,7 +335,8 @@ def _render_rating_dist(rating_dist: dict, title: str):
304335
)])
305336
fig3.update_layout(margin=dict(t=20, b=20, l=20, r=20), height=280,
306337
paper_bgcolor="rgba(0,0,0,0)", plot_bgcolor="rgba(0,0,0,0)",
307-
xaxis=dict(showgrid=False), yaxis=dict(showgrid=False))
338+
xaxis=dict(showgrid=False), yaxis=dict(showgrid=False),
339+
font=dict(family="-apple-system, BlinkMacSystemFont, Segoe UI, sans-serif", color="#1E1E2E"))
308340
st.plotly_chart(fig3, use_container_width=True)
309341

310342

@@ -332,14 +364,15 @@ def _version_sort_key(v):
332364
textposition="top center",
333365
marker=dict(
334366
size=[max(8, min(30, vt[v]["review_count"])) for v in sorted_versions],
335-
color="#37352F",
367+
color="#4F46E5",
336368
),
337-
line=dict(color="#37352F", width=2),
369+
line=dict(color="#4F46E5", width=2),
338370
))
339371
fig4.update_layout(margin=dict(t=20, b=20, l=20, r=20), height=280,
340372
paper_bgcolor="rgba(0,0,0,0)", plot_bgcolor="rgba(0,0,0,0)",
341373
xaxis=dict(showgrid=False, title="版本"),
342-
yaxis=dict(showgrid=True, title="平均评分", range=[0.5, 5.5]))
374+
yaxis=dict(showgrid=True, title="平均评分", range=[0.5, 5.5]),
375+
font=dict(family="-apple-system, BlinkMacSystemFont, Segoe UI, sans-serif", color="#1E1E2E"))
343376
st.plotly_chart(fig4, use_container_width=True)
344377

345378

@@ -373,21 +406,22 @@ def _render_time_trend(analyzed_reviews: list[dict], title: str):
373406
fig_time = go.Figure()
374407
fig_time.add_trace(go.Scatter(
375408
x=sorted_weeks, y=[weekly[w]["positive"] for w in sorted_weeks],
376-
name="正面", mode="lines", line=dict(color="#4285F4", width=2), stackgroup="one",
409+
name="正面", mode="lines", line=dict(color="#4F46E5", width=2), stackgroup="one",
377410
))
378411
fig_time.add_trace(go.Scatter(
379412
x=sorted_weeks, y=[weekly[w]["neutral"] for w in sorted_weeks],
380-
name="中性", mode="lines", line=dict(color="#9AA0A6", width=2), stackgroup="one",
413+
name="中性", mode="lines", line=dict(color="#D1D5DB", width=2), stackgroup="one",
381414
))
382415
fig_time.add_trace(go.Scatter(
383416
x=sorted_weeks, y=[weekly[w]["negative"] for w in sorted_weeks],
384-
name="负面", mode="lines", line=dict(color="#EA8600", width=2), stackgroup="one",
417+
name="负面", mode="lines", line=dict(color="#F59E0B", width=2), stackgroup="one",
385418
))
386419
fig_time.update_layout(
387420
margin=dict(t=20, b=20, l=20, r=20), height=280,
388421
paper_bgcolor="rgba(0,0,0,0)", plot_bgcolor="rgba(0,0,0,0)",
389422
xaxis=dict(showgrid=False), yaxis=dict(showgrid=True, title="评论数"),
390423
legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1),
424+
font=dict(family="-apple-system, BlinkMacSystemFont, Segoe UI, sans-serif", color="#1E1E2E"),
391425
)
392426
st.plotly_chart(fig_time, use_container_width=True)
393427

@@ -627,7 +661,7 @@ def _show_results():
627661

628662
st.markdown(
629663
f'{plat_label} {stars} {sent_emoji} '
630-
f'<span style="color:#787774;font-size:12px;">v{html_mod.escape(str(version))} | {html_mod.escape(date)} | {html_mod.escape(category)}</span>\n\n'
664+
f'<span style="color:#6B7280;font-size:12px;">v{html_mod.escape(str(version))} | {html_mod.escape(date)} | {html_mod.escape(category)}</span>\n\n'
631665
f'> {html_mod.escape(content)}',
632666
unsafe_allow_html=True,
633667
)
@@ -751,7 +785,7 @@ def _show_results():
751785
<div class="app-info">
752786
<div class="app-name">{html_mod.escape(name)}</div>
753787
<div class="app-category">{html_mod.escape(category)}</div>
754-
<div style="font-size:13px;color:#787774;margin-top:4px;">
788+
<div style="font-size:13px;color:#6B7280;margin-top:4px;">
755789
{"✅ App Store" if ios_result else "❌ App Store"}
756790
&nbsp;|&nbsp;
757791
{"✅ Google Play" if gplay_result else "❌ Google Play"}

0 commit comments

Comments
 (0)