NiceGUI 一个第三方 图标库

15 阅读8分钟

图:

image.png

代码:

from nicegui import ui, events
from typing import Dict, List

# ========== 1. 定义图标分类和对应图标 ==========
ICON_CATEGORIES: Dict[str, List[str]] = {
    '全部图标': [
        # 基础操作
        'fa-solid fa-plus', 'fa-solid fa-pen-to-square', 'fa-solid fa-trash-can',
        'fa-solid fa-floppy-disk', 'fa-solid fa-xmark', 'fa-solid fa-magnifying-glass',
        'fa-solid fa-bars', 'fa-solid fa-home', 'fa-solid fa-gear', 'fa-solid fa-user',
        'fa-solid fa-envelope', 'fa-solid fa-phone', 'fa-solid fa-lock', 'fa-solid fa-lock-open',
        'fa-solid fa-arrows-rotate', 'fa-solid fa-download', 'fa-solid fa-upload',
        'fa-solid fa-share-nodes', 'fa-solid fa-heart', 'fa-solid fa-star', 'fa-solid fa-check',
        'fa-solid fa-circle-exclamation', 'fa-solid fa-triangle-exclamation', 'fa-solid fa-info-circle',
        'fa-solid fa-question-circle', 'fa-solid fa-eye', 'fa-solid fa-eye-slash',
        
        # 方向/箭头
        'fa-solid fa-arrow-up', 'fa-solid fa-arrow-down', 'fa-solid fa-arrow-left', 'fa-solid fa-arrow-right',
        'fa-solid fa-arrow-up-right-from-square', 'fa-solid fa-arrow-up-left-from-square',
        'fa-solid fa-arrow-down-right-to-square', 'fa-solid fa-arrow-down-left-to-square',
        'fa-solid fa-chevron-up', 'fa-solid fa-chevron-down', 'fa-solid fa-chevron-left', 'fa-solid fa-chevron-right',
        'fa-solid fa-angle-up', 'fa-solid fa-angle-down', 'fa-solid fa-angle-left', 'fa-solid fa-angle-right',
        
        # 分类/筛选
        'fa-solid fa-filter', 'fa-solid fa-sort', 'fa-solid fa-sort-up', 'fa-solid fa-sort-down',
        'fa-solid fa-ellipsis-vertical', 'fa-solid fa-ellipsis-horizontal',
        
        # 文件/文件夹
        'fa-solid fa-folder', 'fa-solid fa-folder-open', 'fa-solid fa-file', 'fa-solid fa-file-lines',
        'fa-solid fa-file-text', 'fa-solid fa-file-pdf', 'fa-solid fa-file-word', 'fa-solid fa-file-excel',
        'fa-solid fa-file-image', 'fa-solid fa-file-video', 'fa-solid fa-file-audio', 'fa-solid fa-file-code',
        
        # 媒体
        'fa-solid fa-image', 'fa-solid fa-video', 'fa-solid fa-music', 'fa-solid fa-headphones',
        'fa-solid fa-volume-high', 'fa-solid fa-volume-low', 'fa-solid fa-volume-mute', 'fa-solid fa-volume-xmark',
        'fa-solid fa-play', 'fa-solid fa-pause', 'fa-solid fa-stop', 'fa-solid fa-forward', 'fa-solid fa-backward',
        
        # 设备
        'fa-solid fa-laptop', 'fa-solid fa-desktop', 'fa-solid fa-mobile-screen', 'fa-solid fa-tablet-screen-button',
        'fa-solid fa-keyboard', 'fa-solid fa-mouse', 'fa-solid fa-print', 'fa-solid fa-scanner',
        'fa-solid fa-wifi', 'fa-solid fa-bluetooth-b', 'fa-solid fa-battery-full', 'fa-solid fa-battery-half',
        'fa-solid fa-battery-empty', 'fa-solid fa-plug',
        
        # 办公/工具
        'fa-solid fa-pen', 'fa-solid fa-pencil-alt', 'fa-solid fa-pen-ruler', 'fa-solid fa-eraser',
        'fa-solid fa-scissors', 'fa-solid fa-glue', 'fa-solid fa-ruler-combined', 'fa-solid fa-triangle-ruler',
        'fa-solid fa-compass', 'fa-solid fa-drafting-compass', 'fa-solid fa-calculator', 'fa-solid fa-clock',
        'fa-solid fa-alarm-clock', 'fa-solid fa-stopwatch', 'fa-solid fa-calendar-days', 'fa-solid fa-calendar-check',
        
        # 社交/通讯
        'fa-solid fa-envelope-open', 'fa-solid fa-comment', 'fa-solid fa-comment-dots', 'fa-solid fa-comments',
        'fa-solid fa-user-group', 'fa-solid fa-users', 'fa-solid fa-address-book', 'fa-solid fa-id-card',
        'fa-solid fa-phone-flip', 'fa-solid fa-sms', 'fa-solid fa-share-alt', 'fa-solid fa-link',
        
        # 购物/支付
        'fa-solid fa-cart-shopping', 'fa-solid fa-bag-shopping', 'fa-solid fa-credit-card', 'fa-solid fa-money-bill',
        'fa-solid fa-tag', 'fa-solid fa-percent', 'fa-solid fa-barcode', 'fa-solid fa-qrcode',
        'fa-solid fa-receipt',
        
        # 交通
        'fa-solid fa-car', 'fa-solid fa-truck', 'fa-solid fa-bus', 'fa-solid fa-bicycle',
        'fa-solid fa-motorcycle', 'fa-solid fa-plane', 'fa-solid fa-ship', 'fa-solid fa-train',
        'fa-solid fa-road', 'fa-solid fa-location-dot', 'fa-solid fa-map', 'fa-solid fa-map-location-dot',
        
        # 其他工具
        'fa-solid fa-copy', 'fa-solid fa-cut', 'fa-solid fa-paste', 'fa-solid fa-undo', 'fa-solid fa-redo',
        'fa-solid fa-select-all', 'fa-solid fa-maximize', 'fa-solid fa-minimize', 'fa-solid fa-expand',
        'fa-solid fa-compress', 'fa-solid fa-search-plus', 'fa-solid fa-search-minus', 'fa-solid fa-lock-keyhole',
        'fa-solid fa-unlock-keyhole', 'fa-solid fa-shield-halved', 'fa-solid fa-flag', 'fa-solid fa-bookmark'
    ],
    '基础操作': [
        'fa-solid fa-plus', 'fa-solid fa-pen-to-square', 'fa-solid fa-trash-can',
        'fa-solid fa-floppy-disk', 'fa-solid fa-xmark', 'fa-solid fa-magnifying-glass',
        'fa-solid fa-bars', 'fa-solid fa-home', 'fa-solid fa-gear', 'fa-solid fa-user',
        'fa-solid fa-envelope', 'fa-solid fa-phone', 'fa-solid fa-lock', 'fa-solid fa-lock-open',
        'fa-solid fa-arrows-rotate', 'fa-solid fa-download', 'fa-solid fa-upload',
        'fa-solid fa-share-nodes', 'fa-solid fa-heart', 'fa-solid fa-star', 'fa-solid fa-check',
        'fa-solid fa-circle-exclamation', 'fa-solid fa-triangle-exclamation', 'fa-solid fa-info-circle',
        'fa-solid fa-question-circle', 'fa-solid fa-eye', 'fa-solid fa-eye-slash'
    ],
    '方向箭头': [
        'fa-solid fa-arrow-up', 'fa-solid fa-arrow-down', 'fa-solid fa-arrow-left', 'fa-solid fa-arrow-right',
        'fa-solid fa-arrow-up-right-from-square', 'fa-solid fa-arrow-up-left-from-square',
        'fa-solid fa-arrow-down-right-to-square', 'fa-solid fa-arrow-down-left-to-square',
        'fa-solid fa-chevron-up', 'fa-solid fa-chevron-down', 'fa-solid fa-chevron-left', 'fa-solid fa-chevron-right',
        'fa-solid fa-angle-up', 'fa-solid fa-angle-down', 'fa-solid fa-angle-left', 'fa-solid fa-angle-right'
    ],
    '文件文件夹': [
        'fa-solid fa-folder', 'fa-solid fa-folder-open', 'fa-solid fa-file', 'fa-solid fa-file-lines',
        'fa-solid fa-file-text', 'fa-solid fa-file-pdf', 'fa-solid fa-file-word', 'fa-solid fa-file-excel',
        'fa-solid fa-file-image', 'fa-solid fa-file-video', 'fa-solid fa-file-audio', 'fa-solid fa-file-code'
    ],
    '媒体控制': [
        'fa-solid fa-image', 'fa-solid fa-video', 'fa-solid fa-music', 'fa-solid fa-headphones',
        'fa-solid fa-volume-high', 'fa-solid fa-volume-low', 'fa-solid fa-volume-mute', 'fa-solid fa-volume-xmark',
        'fa-solid fa-play', 'fa-solid fa-pause', 'fa-solid fa-stop', 'fa-solid fa-forward', 'fa-solid fa-backward'
    ],
    '电子设备': [
        'fa-solid fa-laptop', 'fa-solid fa-desktop', 'fa-solid fa-mobile-screen', 'fa-solid fa-tablet-screen-button',
        'fa-solid fa-keyboard', 'fa-solid fa-mouse', 'fa-solid fa-print', 'fa-solid fa-scanner',
        'fa-solid fa-wifi', 'fa-solid fa-bluetooth-b', 'fa-solid fa-battery-full', 'fa-solid fa-battery-half',
        'fa-solid fa-battery-empty', 'fa-solid fa-plug'
    ],
    '办公工具': [
        'fa-solid fa-pen', 'fa-solid fa-pencil-alt', 'fa-solid fa-pen-ruler', 'fa-solid fa-eraser',
        'fa-solid fa-scissors', 'fa-solid fa-glue', 'fa-solid fa-ruler-combined', 'fa-solid fa-triangle-ruler',
        'fa-solid fa-compass', 'fa-solid fa-drafting-compass', 'fa-solid fa-calculator', 'fa-solid fa-clock',
        'fa-solid fa-alarm-clock', 'fa-solid fa-stopwatch', 'fa-solid fa-calendar-days', 'fa-solid fa-calendar-check'
    ],
    '社交通讯': [
        'fa-solid fa-envelope-open', 'fa-solid fa-comment', 'fa-solid fa-comment-dots', 'fa-solid fa-comments',
        'fa-solid fa-user-group', 'fa-solid fa-users', 'fa-solid fa-address-book', 'fa-solid fa-id-card',
        'fa-solid fa-phone-flip', 'fa-solid fa-sms', 'fa-solid fa-share-alt', 'fa-solid fa-link'
    ],
    '购物支付': [
        'fa-solid fa-cart-shopping', 'fa-solid fa-bag-shopping', 'fa-solid fa-credit-card', 'fa-solid fa-money-bill',
        'fa-solid fa-tag', 'fa-solid fa-percent', 'fa-solid fa-barcode', 'fa-solid fa-qrcode',
        'fa-solid fa-receipt'
    ],
    '交通出行': [
        'fa-solid fa-car', 'fa-solid fa-truck', 'fa-solid fa-bus', 'fa-solid fa-bicycle',
        'fa-solid fa-motorcycle', 'fa-solid fa-plane', 'fa-solid fa-ship', 'fa-solid fa-train',
        'fa-solid fa-road', 'fa-solid fa-location-dot', 'fa-solid fa-map', 'fa-solid fa-map-location-dot'
    ],
    '其他工具': [
        'fa-solid fa-copy', 'fa-solid fa-cut', 'fa-solid fa-paste', 'fa-solid fa-undo', 'fa-solid fa-redo',
        'fa-solid fa-select-all', 'fa-solid fa-maximize', 'fa-solid fa-minimize', 'fa-solid fa-expand',
        'fa-solid fa-compress', 'fa-solid fa-search-plus', 'fa-solid fa-search-minus', 'fa-solid fa-lock-keyhole',
        'fa-solid fa-unlock-keyhole', 'fa-solid fa-shield-halved', 'fa-solid fa-flag', 'fa-solid fa-bookmark',
        'home'
    ]
}

# 复制图标名称函数
def copy_icon_name(name: str):
    ui.run_javascript(f'navigator.clipboard.writeText(`{name}`)')
    ui.notify(f'已复制: {name}', type='positive', timeout=2000)

def main():
    # 加载国内可用的Font Awesome CDN
    ui.add_head_html('''
        <link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css">
    ''')

    # 页面基础配置
    ui.page_title('NiceGUI 3.4.0 图标展示库')
    ui.colors(primary='#2196F3', secondary='#4CAF50')

    # 存储图标卡片引用和当前筛选状态
    icon_cards = {}  # key: 图标代码, value: 卡片元素
    current_category = '全部图标'
    current_search_text = ''

    # ========== 2. 顶部导航栏(含分类筛选+搜索) ==========
    with ui.header(elevated=True).style('padding: 1rem 2rem; background-color: white; display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap'):
        # 标题
        ui.label('NiceGUI 图标库').style('font-size: 1.8rem; font-weight: bold; color: #2196F3; margin-right: 1rem')
        
        # 分类筛选下拉框
        category_select = ui.select(
            options=list(ICON_CATEGORIES.keys()),
            value='全部图标',
            on_change=lambda e: update_filter(category=e.value)
        ).props('rounded outlined').style('width: 180px; min-width: 150px')
        # 下拉框前置图标
        category_select.add_slot('prepend', '<i class="fa-solid fa-layer-group"></i>')
        
        # 搜索框
        search_input = ui.input(
            placeholder='搜索图标(如:car、file、arrow)',
            on_change=lambda e: update_filter(search_text=e.value)
        ).props('rounded outlined').style('width: 300px; min-width: 200px')
        # 搜索框前置图标
        search_input.add_slot('prepend', '<i class="fa-solid fa-magnifying-glass"></i>')
        
        # 统计显示
        count_label = ui.label(f'共 {len(ICON_CATEGORIES["全部图标"])} 个图标').style('margin-left: auto; color: #666')

    # ========== 3. 图标展示区域(规整阵列) ==========
    with ui.scroll_area().style('padding: 2rem; height: calc(100vh - 140px); background-color: #f8f9fa'):
        # 固定8列网格布局,居中显示
        grid = ui.grid(columns='repeat(8, 1fr)').style('gap: 1.5rem; max-width: 1600px; margin: 0 auto')
        
        # 生成所有图标卡片
        all_icons = ICON_CATEGORIES['全部图标']
        for icon_code in all_icons:
            with grid:
                # 统一尺寸的卡片,带hover效果
                card = ui.card().style('''
                    padding: 1.5rem 1rem; 
                    text-align: center; 
                    border-radius: 8px; 
                    box-shadow: 0 2px 6px rgba(0,0,0,0.08);
                    width: 100%; 
                    height: 220px; 
                    display: flex; 
                    flex-direction: column; 
                    align-items: center; 
                    justify-content: center;
                    transition: all 0.2s ease;
                ''').on('mouseenter', lambda e: e.sender.style('box-shadow: 0 4px 12px rgba(0,0,0,0.15)')) \
                  .on('mouseleave', lambda e: e.sender.style('box-shadow: 0 2px 6px rgba(0,0,0,0.08)'))
                
                with card:
                    # 图标(固定大小)
                    ui.icon(icon_code).style('font-size: 3.5rem; margin-bottom: 1rem; color: #2196F3')
                    # 图标代码(换行显示)
                    ui.label(icon_code).style('''
                        font-family: Consolas, monospace; 
                        font-size: 13px; 
                        margin-bottom: 1rem; 
                        color: #333;
                        word-break: break-all;
                        line-height: 1.4;
                    ''')
                    # 复制按钮(固定宽度)
                    ui.button('复制', on_click=lambda n=icon_code: copy_icon_name(n)) \
                        .props('outline rounded').style('width: 100px; height: 36px')
            
            # 保存卡片引用
            icon_cards[icon_code] = card

    # ========== 4. 组合筛选函数(分类+搜索) ==========
    def update_filter(category: str = None, search_text: str = None):
        nonlocal current_category, current_search_text
        
        # 更新筛选状态
        if category is not None:
            current_category = category
        if search_text is not None:
            current_search_text = search_text.lower().strip()
        
        # 获取当前分类下的所有图标
        category_icons = ICON_CATEGORIES[current_category]
        match_count = 0
        
        # 遍历所有图标,应用组合筛选
        for icon_code, card in icon_cards.items():
            # 条件1:属于当前分类
            in_category = icon_code in category_icons
            # 条件2:匹配搜索关键词(为空则全部匹配)
            match_search = current_search_text in icon_code.lower() if current_search_text else True
            
            # 显示/隐藏卡片
            if in_category and match_search:
                card.style('display: flex')
                match_count += 1
            else:
                card.style('display: none')
        
        # 更新统计信息
        count_label.set_text(f'找到 {match_count} 个图标({current_category}{len(category_icons)} 个)')

    # ========== 页脚 ==========
    with ui.footer().style('padding: 0.8rem; text-align: center; background-color: #2196F3; color: white'):
        ui.label('NiceGUI 3.4.0 图标展示页 | 支持分类筛选+关键词搜索 | 200+常用图标')

# 兼容多进程的主程序保护语句
if __name__ in {"__main__", "__mp_main__"}:
    main()
    # 启动NiceGUI
    ui.run(
        title='NiceGUI 图标库',
        port=8083,
        reload=True,
        show=True,
        uvicorn_logging_level='warning'
    )