本文将展示如何使用Python的Streamlit库结合CSS来创建一个动态的商品展示页面。我们将逐步分析代码,了解其构成,并展示最终效果。
Streamlit页面配置
首先,我们设置页面的基本配置:
ini
pythonCopy code
import streamlit as st
st.set_page_config(page_title="Hello", page_icon="👋", layout="wide")
这段代码设置了页面的标题、图标和布局。
定义CSS样式
为了增强页面的视觉效果,我们定义了一段CSS样式:
python
pythonCopy code
def local_css1():
st.markdown("""
<style>
.card { /* 卡片样式 */ }
.card:hover { /* 卡片悬浮效果 */ }
/* 其他样式定义 */
</style>
""", unsafe_allow_html=True)
local_css1()
这段CSS定义了卡片的基本样式,如阴影、悬浮效果和布局。
生成模拟商品数据
接下来,我们生成模拟的商品数据:
ini
pythonCopy code
import random
import datetime
def generate_mock_data(num_items=50):
# 生成模拟数据的逻辑
return [/* 商品数据列表 */]
products = generate_mock_data()
这个函数创建了一个包含多个商品的列表,每个商品有名称、价格、评分等属性。
生成星级评分
我们使用一个函数来根据商品评分生成星级评分的HTML代码:
python
pythonCopy code
def get_star_rating(rating):
# 根据评分生成星级评分的HTML
return full_stars_html + half_star_html + empty_stars_html
显示商品
最关键的部分是展示商品信息:
scss
pythonCopy code
def display_products(products, start_idx, end_idx):
# 使用Streamlit的columns方法来展示商品卡片
for i in range(num_rows):
cols = st.columns(num_cols)
for j in range(num_cols):
# 商品卡片的HTML内容
st.markdown(f"""<div class="card">...</div>""", unsafe_allow_html=True)
display_products(products, 0, 40)
这个函数负责将商品数据以卡片形式展示出来。
分页功能
最后,我们通过分页组件来管理大量商品的展示:
ini
pythonCopy code
import streamlit_antd_components as sac
sac.pagination(
total=len(products),
page_size=40,
on_change=handle_page_change,
align='center',
jump=True,
show_total=True,
key='my_pagination'
)
完整代码
ini
import streamlit as st
import streamlit_antd_components as sac
import random
import datetime
# 设置页面配置
st.set_page_config(page_title="Hello", page_icon="👋", layout="wide")
def local_css1():
st.markdown("""
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<style>
.card {
margin-bottom: 10px;
border: 1px solid #ddd;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: box-shadow 0.3s ease-in-out;
display: flex;
flex-direction: column;
min-height: 360px; /* Adjust this value as needed to fit your content */
}
.card:hover {
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
.card-header {
align-items: center;
width: 100%;
}
.card-image {
height: auto;
width: 100%;
object-fit: cover;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
}
.card-body {
display: flex;
}
.card-info, .card-info-right {
flex: 1;
padding: 10px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.card-text {
color: #555;
}
.price {
color: #E07C24;
font-weight: bold;
}
.fa-star {
color: #FFA500; /* Star color */
}
.star-rating {
display: inline-block; /* Stars inline */
}
.card-title {
display: -webkit-box;
-webkit-line-clamp: 6;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1.2em;
max-height: 3.6em; /* Height for two lines of text */
margin: 0;
font-weight: bold;
width: 100%;
transition: max-height 0.3s ease-in-out;
text-decoration: none;
color: #77787b;
}
.card-title-link {
text-decoration: none; /* No underline */
color: inherit; /* Inherits color for consistency */
display: block; /* Makes the entire area clickable */
position: relative; /* Needed for tooltip positioning */
}
.card-title-link:hover .card-title {
max-height: none; /* Remove max-height on hover */
-webkit-line-clamp: none;
overflow: visible;
}
</style>
""", unsafe_allow_html=True)
local_css1()
# 生成模拟商品数据
def generate_mock_data(num_items=50):
current_time = datetime.datetime.now()
return [
{
"name": f"商品{i + 1}",
"price": random.uniform(10.0, 100.0),
"sales": random.randint(1, 500),
"rating_count": random.randint(1, 100),
"rating": random.uniform(1.0, 5.0),
"brand": f"品牌{i + 1}",
"image_url": f"https://picsum.photos/seed/picsum/80/40",
"ranking": random.randint(1, 100),
"shelf_time": (current_time - datetime.timedelta(days=random.randint(1, 365))).strftime('%Y-%m-%d'),
"update_time": (current_time - datetime.timedelta(hours=random.randint(1, 24))).strftime(
'%Y-%m-%d'),
"shipping_fee": round(random.uniform(0.0, 10.0),2),
} for i in range(num_items)
]
# 生成星星评分的HTML代码
def get_star_rating(rating):
# 满星的数量
full_stars = int(rating)
# 半星的数量(如果评分有小数,则显示半星)
half_star = 1 if rating % 1 else 0
# 空星的数量
empty_stars = 5 - full_stars - half_star
# 生成满星图标
full_stars_html = '<i class="fas fa-star"></i>' * full_stars
# 生成半星图标
half_star_html = '<i class="fas fa-star fa-star-half-alt"></i>' * half_star
# 生成空星图标
empty_stars_html = '<i class="far fa-star"></i>' * empty_stars
# 返回拼接好的HTML代码
return full_stars_html + half_star_html + empty_stars_html
# 显示商品
def display_products(products, start_idx, end_idx):
# 每行4个卡片
num_cols = 4
num_rows = (end_idx - start_idx + num_cols - 1) // num_cols
for i in range(num_rows):
cols = st.columns(num_cols) # 创建4列
for j in range(num_cols):
index = start_idx + i * num_cols + j
if index < end_idx and index < len(products):
product = products[index]
with cols[j]:
star_rating_html = get_star_rating(product['rating'])
product['name'] = "With a powerful built-in fan, only a minute Snowman Family will be standing up to its full height. 4 Stakes and 2 ropes included for quick and easy setup. A zipper is designed in the bottom of the inflatable for a heavy object to make it more secure and stable. Plug in, everything pop s up in a minute!"
st.markdown(f"""
<div class="card">
<div class="card-header">
<img class="card-image" src="{product['image_url']}" alt="{product['name']}">
<a href="#" target="_blank" class="card-title-link" data-title="{product['name']}">
<span class="card-title">{product['name']}</span>
</a>
</div>
<div class="card-body">
<div class="card-info">
<p class="card-text price">¥{product['price']:.2f}</p>
<p class="card-text">销量: {product['sales']}</p>
<p class="card-text">排名: {product['ranking']}</p>
<p class="card-text">品牌: {product['brand']}</p>
</div>
<div class="card-info-right">
<p class="card-text"><span class="star-rating">{star_rating_html}</span> ({product['rating_count']}评分)</p>
<p class="card-text">上架时间: {product['shelf_time']}</p>
<p class="card-text">更新时间: {product['update_time']}</p>
<p class="card-text">邮费: {product['shipping_fee']}</p>
</div>
</div>
</div>
""", unsafe_allow_html=True)
def handle_page_change():
st.session_state.page_number = st.session_state.my_pagination
# 运行Streamlit应用
if __name__ == "__main__":
# st.title("商品列表页")
st.info('商品列表页')
if 'page_number' not in st.session_state:
st.session_state['page_number'] = 1
products = generate_mock_data()
PAGE_SIZE = 40
total_products = len(products)
start_idx = (st.session_state.page_number - 1) * PAGE_SIZE
end_idx = start_idx + PAGE_SIZE
display_products(products, start_idx, end_idx)
# 使用sac.pagination组件创建分页导航栏
sac.pagination(
total=total_products,
page_size=PAGE_SIZE,
on_change=handle_page_change,
align='center',
jump=True,
show_total=True,
key='my_pagination'
)
效果图
结论
以上就是使用Streamlit和CSS创建动态商品展示页面的全过程。通过这种方法,我们可以快速搭建一个美观且实用的产品展示界面,非常适合用于产品原型开发或数据集展示。
希望这篇博客能帮助你了解如何结合Streamlit和CSS/HTML来创建动态的Web应用程序。如有任何疑问或进一步的探讨,欢迎点赞和留言交流!