使用Streamlit和CSS创建一个动态商品展示页面

本文将展示如何使用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应用程序。如有任何疑问或进一步的探讨,欢迎点赞和留言交流!

相关推荐
LucianaiB1 小时前
探索CSDN博客数据:使用Python爬虫技术
开发语言·爬虫·python
一个处女座的程序猿O(∩_∩)O1 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
PieroPc3 小时前
Python 写的 智慧记 进销存 辅助 程序 导入导出 excel 可打印
开发语言·python·excel
hackeroink4 小时前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
迷雾漫步者6 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-6 小时前
验证码机制
前端·后端
梧桐树04297 小时前
python常用内建模块:collections
python
燃先生._.7 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
Dream_Snowar7 小时前
速通Python 第三节
开发语言·python