用 nicegui 3.0 + sqlite3 做个简单博客

原生版 图:

美化版 图:

数据库sqlite3(database.py):

python 复制代码
import sqlite3
from datetime import datetime

class BlogDB:
    def __init__(self, db_name='blog.db'):
        self.db_name = db_name
        self.init_db()
    
    def init_db(self):
        """初始化数据库表"""
        conn = sqlite3.connect(self.db_name)
        cursor = conn.cursor()
        
        # 创建文章表
        cursor.execute('''
        CREATE TABLE IF NOT EXISTS posts (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            title TEXT NOT NULL,
            content TEXT NOT NULL,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
        ''')
        
        # 创建评论表
        cursor.execute('''
        CREATE TABLE IF NOT EXISTS comments (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            post_id INTEGER,
            author TEXT NOT NULL,
            content TEXT NOT NULL,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            FOREIGN KEY (post_id) REFERENCES posts (id) ON DELETE CASCADE
        )
        ''')
        
        conn.commit()
        conn.close()
    
    def get_connection(self):
        """获取数据库连接"""
        conn = sqlite3.connect(self.db_name)
        conn.row_factory = sqlite3.Row  # 返回字典格式
        return conn
    
    # 文章相关操作
    def create_post(self, title, content):
        """创建新文章"""
        conn = self.get_connection()
        cursor = conn.cursor()
        cursor.execute(
            'INSERT INTO posts (title, content) VALUES (?, ?)',
            (title, content)
        )
        post_id = cursor.lastrowid
        conn.commit()
        conn.close()
        return post_id
    
    def get_all_posts(self):
        """获取所有文章"""
        conn = self.get_connection()
        cursor = conn.cursor()
        cursor.execute('SELECT * FROM posts ORDER BY created_at DESC')
        posts = cursor.fetchall()
        conn.close()
        return posts
    
    def get_post(self, post_id):
        """获取单篇文章"""
        conn = self.get_connection()
        cursor = conn.cursor()
        cursor.execute('SELECT * FROM posts WHERE id = ?', (post_id,))
        post = cursor.fetchone()
        conn.close()
        return post
    
    def update_post(self, post_id, title, content):
        """更新文章"""
        conn = self.get_connection()
        cursor = conn.cursor()
        cursor.execute(
            'UPDATE posts SET title = ?, content = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?',
            (title, content, post_id)
        )
        conn.commit()
        conn.close()
        return cursor.rowcount > 0
    
    def delete_post(self, post_id):
        """删除文章"""
        conn = self.get_connection()
        cursor = conn.cursor()
        cursor.execute('DELETE FROM posts WHERE id = ?', (post_id,))
        conn.commit()
        conn.close()
        return cursor.rowcount > 0
    
    # 评论相关操作
    def add_comment(self, post_id, author, content):
        """添加评论"""
        conn = self.get_connection()
        cursor = conn.cursor()
        cursor.execute(
            'INSERT INTO comments (post_id, author, content) VALUES (?, ?, ?)',
            (post_id, author, content)
        )
        conn.commit()
        conn.close()
    
    def get_comments(self, post_id):
        """获取文章的评论"""
        conn = self.get_connection()
        cursor = conn.cursor()
        cursor.execute(
            'SELECT * FROM comments WHERE post_id = ? ORDER BY created_at DESC',
            (post_id,)
        )
        comments = cursor.fetchall()
        conn.close()
        return comments

原生代码(main.py):

python 复制代码
from nicegui import ui
import database

# 初始化数据库
db = database.BlogDB()

def create_blog_ui():
    """创建博客界面"""
    
    # 状态变量
    current_post_id = None
    edit_mode = False
    
    # 标题
    ui.label('我的博客系统')
    
    # 创建容器 - 用于切换视图
    main_container = ui.column()
    edit_container = ui.column()
    
    def show_main_view():
        """显示主视图(文章列表)"""
        edit_container.clear()
        edit_container.visible = False
        main_container.clear()
        main_container.visible = True
        
        with main_container:
            # 标题
            ui.label('博客文章列表')
            
            # 功能按钮
            with ui.row():
                ui.button('写新文章', on_click=show_create_post)
                ui.button('刷新列表', on_click=show_main_view)
            
            # 文章列表
            posts = db.get_all_posts()
            
            if not posts:
                ui.label('暂无文章,点击"写新文章"开始创作')
                return
            
            for post in posts:
                with ui.card():
                    # 文章标题
                    ui.label(post['title'])
                    
                    # 预览内容
                    preview = post['content']
                    if len(preview) > 200:
                        preview = preview[:200] + '...'
                    ui.label(preview)
                    
                    # 时间信息
                    ui.label(f'创建时间: {post["created_at"]}')
                    
                    # 操作按钮
                    with ui.row():
                        ui.button('查看详情', on_click=lambda p=post: show_post_detail(p['id']))
                        ui.button('编辑', on_click=lambda p=post: show_edit_post(p['id']))
                        
                        # 删除按钮 - 带确认
                        def delete_with_confirm(p_id):
                            def confirm_delete():
                                db.delete_post(p_id)
                                ui.notify('文章已删除')
                                show_main_view()
                            
                            # 使用对话框确认
                            with ui.dialog() as dialog:
                                with ui.card():
                                    ui.label('确认删除')
                                    ui.label('确定要删除这篇文章吗?')
                                    with ui.row():
                                        ui.button('确定', on_click=lambda: [dialog.close(), confirm_delete()])
                                        ui.button('取消', on_click=dialog.close)
                            dialog.open()
                        
                        ui.button('删除', on_click=lambda p=post: delete_with_confirm(p['id']))
    
    def show_create_post():
        """显示创建文章界面"""
        nonlocal current_post_id, edit_mode
        current_post_id = None
        edit_mode = True
        
        main_container.visible = False
        edit_container.clear()
        edit_container.visible = True
        
        with edit_container:
            ui.label('创建新文章')
            
            # 标题输入
            title_input = ui.input('文章标题')
            
            # 内容输入
            content_input = ui.textarea('文章内容')
            
            # 按钮
            with ui.row():
                ui.button('保存文章', on_click=lambda: save_post(title_input, content_input))
                ui.button('取消', on_click=show_main_view)
    
    def show_edit_post(post_id):
        """显示编辑文章界面"""
        nonlocal current_post_id, edit_mode
        current_post_id = post_id
        edit_mode = True
        
        post = db.get_post(post_id)
        if not post:
            ui.notify('文章不存在')
            show_main_view()
            return
        
        main_container.visible = False
        edit_container.clear()
        edit_container.visible = True
        
        with edit_container:
            ui.label('编辑文章')
            
            # 标题输入
            title_input = ui.input('文章标题')
            title_input.value = post['title']
            
            # 内容输入
            content_input = ui.textarea('文章内容')
            content_input.value = post['content']
            
            # 按钮
            with ui.row():
                ui.button('保存修改', on_click=lambda: save_post(title_input, content_input))
                ui.button('取消', on_click=show_main_view)
    
    def save_post(title_input, content_input):
        """保存文章"""
        nonlocal current_post_id
        
        title = title_input.value.strip()
        content = content_input.value.strip()
        
        if not title:
            ui.notify('请输入文章标题')
            return
        
        if not content:
            ui.notify('请输入文章内容')
            return
        
        try:
            if current_post_id is None:
                # 创建新文章
                db.create_post(title, content)
                ui.notify('文章创建成功')
            else:
                # 更新文章
                db.update_post(current_post_id, title, content)
                ui.notify('文章更新成功')
            
            show_main_view()
        except Exception as e:
            ui.notify(f'保存失败: {str(e)}')
    
    def show_post_detail(post_id):
        """显示文章详情"""
        nonlocal current_post_id
        current_post_id = post_id
        
        post = db.get_post(post_id)
        if not post:
            ui.notify('文章不存在')
            show_main_view()
            return
        
        main_container.visible = False
        edit_container.clear()
        edit_container.visible = True
        
        with edit_container:
            # 返回按钮
            ui.button('返回列表', on_click=show_main_view)
            
            # 文章内容
            ui.label(post['title'])
            ui.label(f'发布时间: {post["created_at"]}')
            
            with ui.card():
                # 显示多行内容
                lines = post['content'].split('\n')
                for line in lines:
                    ui.label(line)
            
            # 操作按钮
            with ui.row():
                ui.button('编辑文章', on_click=lambda: show_edit_post(post_id))
                
                # 删除按钮
                def delete_post():
                    def confirm_delete():
                        db.delete_post(post_id)
                        ui.notify('文章已删除')
                        show_main_view()
                    
                    # 确认对话框
                    with ui.dialog() as dialog:
                        with ui.card():
                            ui.label('确认删除')
                            ui.label('确定要删除这篇文章吗?')
                            with ui.row():
                                ui.button('确定', on_click=lambda: [dialog.close(), confirm_delete()])
                                ui.button('取消', on_click=dialog.close)
                    dialog.open()
                
                ui.button('删除文章', on_click=delete_post)
            
            # 评论部分
            ui.label('评论')
            
            # 添加评论
            with ui.card():
                comment_author = ui.input('你的名字')
                comment_content = ui.textarea('评论内容')
                
                def add_comment():
                    author = comment_author.value.strip()
                    content = comment_content.value.strip()
                    
                    if not author:
                        ui.notify('请输入名字')
                        return
                    
                    if not content:
                        ui.notify('请输入评论内容')
                        return
                    
                    try:
                        db.add_comment(post_id, author, content)
                        ui.notify('评论发表成功')
                        comment_author.value = ''
                        comment_content.value = ''
                        load_comments()
                    except Exception as e:
                        ui.notify(f'评论失败: {str(e)}')
                
                ui.button('发表评论', on_click=add_comment)
            
            # 评论列表
            comments_container = ui.column()
            
            def load_comments():
                comments_container.clear()
                comments = db.get_comments(post_id)
                
                if not comments:
                    ui.label('暂无评论')
                    return
                
                for comment in comments:
                    with comments_container:
                        with ui.card():
                            ui.label(f'{comment["author"]}')
                            ui.label(comment['content'])
                            ui.label(f'评论时间: {comment["created_at"]}')
            
            # 初始加载评论
            load_comments()
    
    # 初始显示主视图
    show_main_view()

# 创建界面
create_blog_ui()

# 运行应用
ui.run(title='我的博客系统', port=8080)

特性说明

这个版本完全使用 NiceGUI 的原生功能:

  1. 不使用 .style() :依赖默认样式

  2. 不使用 .classes() :不使用 CSS 类

  3. 使用原生组件

    • ui.label() 显示文本
    • ui.button() 创建按钮
    • ui.input()ui.textarea() 用于输入
    • ui.card() 创建卡片容器
    • ui.dialog() 创建对话框
    • ui.column()ui.row() 布局
  4. 功能完整

    • 文章列表展示
    • 创建、编辑、删除文章
    • 查看文章详情
    • 添加评论
    • 确认对话框

运行方式:

bash

复制下载

css 复制代码
pip install nicegui
python main.py

访问 http://localhost:8080 即可使用博客系统。

美化版代码:

python 复制代码
from nicegui import ui
import database

# 初始化数据库
db = database.BlogDB()

def create_blog_ui():
    """创建博客界面"""
    
    # 状态变量
    current_post_id = None
    edit_mode = False
    
    # 主容器 - 使用固定宽度居中布局
    with ui.column().classes('mx-auto my-8 w-full max-w-6xl'):
        # 顶部标题栏
        with ui.row().classes('w-full justify-between items-center p-4 bg-blue-50 rounded-lg shadow mb-8'):
            ui.label('📝 我的博客系统').classes('text-3xl font-bold text-blue-800')
            
            with ui.row():
                ui.button('写新文章', on_click=lambda: show_create_post()).classes('bg-green-500 text-white hover:bg-green-600 px-4 py-2 rounded-lg')
                ui.button('刷新列表', on_click=lambda: show_main_view).classes('bg-blue-500 text-white hover:bg-blue-600 px-4 py-2 rounded-lg ml-2')
        
        # 主内容区域
        main_container = ui.column().classes('w-full')
        edit_container = ui.column().classes('w-full')
        
        def show_main_view():
            """显示主视图(文章列表)"""
            edit_container.visible = False
            main_container.clear()
            main_container.visible = True
            
            with main_container:
                # 页面标题
                ui.label('📰 博客文章列表').classes('text-2xl font-bold text-gray-800 mb-6')
                
                # 文章列表
                posts = db.get_all_posts()
                
                if not posts:
                    with ui.card().classes('w-full p-8 text-center'):
                        ui.icon('edit_note', size='xl').classes('text-gray-400 mb-4')
                        ui.label('暂无文章').classes('text-xl text-gray-600 mb-2')
                        ui.label('点击"写新文章"按钮开始您的创作之旅').classes('text-gray-500')
                    return
                
                # 文章网格布局
                with ui.grid(columns=1).classes('w-full gap-6'):
                    for post in posts:
                        with ui.card().classes('w-full hover:shadow-lg transition-shadow duration-300'):
                            # 卡片头部
                            with ui.row().classes('justify-between items-start mb-4'):
                                ui.label(post['title']).classes('text-xl font-bold text-gray-800 truncate flex-grow')
                                ui.label(f'📅 {post["created_at"]}').classes('text-sm text-gray-500 ml-4')
                            
                            # 文章内容预览
                            preview = post['content']
                            if len(preview) > 300:
                                preview = preview[:300] + '...'
                            ui.label(preview).classes('text-gray-600 mb-4 line-clamp-3')
                            
                            # 操作按钮区域
                            with ui.row().classes('justify-end gap-2'):
                                ui.button('👁️ 查看详情', on_click=lambda p=post: show_post_detail(p['id'])).classes('bg-blue-100 text-blue-700 hover:bg-blue-200 px-3 py-1 rounded')
                                ui.button('✏️ 编辑', on_click=lambda p=post: show_edit_post(p['id'])).classes('bg-yellow-100 text-yellow-700 hover:bg-yellow-200 px-3 py-1 rounded')
                                
                                # 删除按钮 - 带确认
                                def delete_with_confirm(p_id, p_title):
                                    def confirm_delete():
                                        db.delete_post(p_id)
                                        ui.notify(f'文章"{p_title}"已删除', type='positive')
                                        show_main_view()
                                    
                                    # 使用对话框确认
                                    with ui.dialog() as dialog:
                                        with ui.card().classes('p-6 w-96'):
                                            ui.icon('warning', color='red', size='xl').classes('mx-auto mb-4')
                                            ui.label('确认删除').classes('text-xl font-bold text-center mb-2')
                                            ui.label(f'确定要删除文章"{p_title}"吗?此操作不可恢复。').classes('text-gray-600 text-center mb-6')
                                            with ui.row().classes('justify-center gap-4'):
                                                ui.button('确定删除', on_click=lambda: [dialog.close(), confirm_delete()]).classes('bg-red-500 text-white hover:bg-red-600 px-4 py-2 rounded')
                                                ui.button('取消', on_click=dialog.close).classes('bg-gray-200 text-gray-700 hover:bg-gray-300 px-4 py-2 rounded')
                                    dialog.open()
                                
                                ui.button('🗑️ 删除', on_click=lambda p=post: delete_with_confirm(p['id'], p['title'])).classes('bg-red-100 text-red-700 hover:bg-red-200 px-3 py-1 rounded')
        
        def show_create_post():
            """显示创建文章界面"""
            nonlocal current_post_id, edit_mode
            current_post_id = None
            edit_mode = True
            
            main_container.visible = False
            edit_container.clear()
            edit_container.visible = True
            
            with edit_container:
                # 页面标题
                with ui.row().classes('items-center mb-6'):
                    ui.icon('add_circle', color='green', size='lg')
                    ui.label('创作新文章').classes('text-2xl font-bold text-gray-800 ml-2')
                
                # 表单区域
                with ui.card().classes('w-full p-6'):
                    # 标题输入
                    ui.label('文章标题').classes('text-lg font-semibold text-gray-700 mb-2')
                    title_input = ui.input(placeholder='请输入文章标题...').classes('w-full p-3 border rounded-lg mb-6 focus:ring-2 focus:ring-blue-500 focus:border-blue-500')
                    
                    # 内容输入
                    ui.label('文章内容').classes('text-lg font-semibold text-gray-700 mb-2')
                    content_input = ui.textarea(placeholder='开始创作您的内容...').classes('w-full h-96 p-3 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500')
                    
                    # 操作按钮
                    with ui.row().classes('justify-end gap-4 mt-8'):
                        ui.button('保存文章', on_click=lambda: save_post(title_input, content_input)).classes('bg-green-500 text-white hover:bg-green-600 px-6 py-3 rounded-lg text-lg')
                        ui.button('取消', on_click=show_main_view).classes('bg-gray-300 text-gray-700 hover:bg-gray-400 px-6 py-3 rounded-lg text-lg')
        
        def show_edit_post(post_id):
            """显示编辑文章界面"""
            nonlocal current_post_id, edit_mode
            current_post_id = post_id
            edit_mode = True
            
            post = db.get_post(post_id)
            if not post:
                ui.notify('文章不存在', type='warning')
                show_main_view()
                return
            
            main_container.visible = False
            edit_container.clear()
            edit_container.visible = True
            
            with edit_container:
                # 页面标题
                with ui.row().classes('items-center mb-6'):
                    ui.icon('edit', color='yellow', size='lg')
                    ui.label('编辑文章').classes('text-2xl font-bold text-gray-800 ml-2')
                
                # 表单区域
                with ui.card().classes('w-full p-6'):
                    # 标题输入
                    ui.label('文章标题').classes('text-lg font-semibold text-gray-700 mb-2')
                    title_input = ui.input(placeholder='请输入文章标题...').classes('w-full p-3 border rounded-lg mb-6 focus:ring-2 focus:ring-blue-500 focus:border-blue-500')
                    title_input.value = post['title']
                    
                    # 内容输入
                    ui.label('文章内容').classes('text-lg font-semibold text-gray-700 mb-2')
                    content_input = ui.textarea(placeholder='开始编辑您的内容...').classes('w-full h-96 p-3 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500')
                    content_input.value = post['content']
                    
                    # 操作按钮
                    with ui.row().classes('justify-end gap-4 mt-8'):
                        ui.button('保存修改', on_click=lambda: save_post(title_input, content_input)).classes('bg-yellow-500 text-white hover:bg-yellow-600 px-6 py-3 rounded-lg text-lg')
                        ui.button('取消', on_click=show_main_view).classes('bg-gray-300 text-gray-700 hover:bg-gray-400 px-6 py-3 rounded-lg text-lg')
        
        def save_post(title_input, content_input):
            """保存文章"""
            nonlocal current_post_id
            
            title = title_input.value.strip()
            content = content_input.value.strip()
            
            if not title:
                ui.notify('请输入文章标题', type='warning')
                return
            
            if not content:
                ui.notify('请输入文章内容', type='warning')
                return
            
            try:
                if current_post_id is None:
                    # 创建新文章
                    db.create_post(title, content)
                    ui.notify('🎉 文章创建成功!', type='positive')
                else:
                    # 更新文章
                    db.update_post(current_post_id, title, content)
                    ui.notify('✅ 文章更新成功!', type='positive')
                
                show_main_view()
            except Exception as e:
                ui.notify(f'保存失败: {str(e)}', type='negative')
        
        def show_post_detail(post_id):
            """显示文章详情"""
            nonlocal current_post_id
            current_post_id = post_id
            
            post = db.get_post(post_id)
            if not post:
                ui.notify('文章不存在', type='warning')
                show_main_view()
                return
            
            main_container.visible = False
            edit_container.clear()
            edit_container.visible = True
            
            with edit_container:
                # 返回按钮和标题
                with ui.row().classes('justify-between items-center mb-6'):
                    ui.button('← 返回列表', on_click=show_main_view).classes('bg-gray-200 text-gray-700 hover:bg-gray-300 px-4 py-2 rounded-lg')
                    ui.label('文章详情').classes('text-2xl font-bold text-gray-800')
                
                # 文章内容卡片
                with ui.card().classes('w-full p-8 mb-8'):
                    # 文章标题
                    ui.label(post['title']).classes('text-3xl font-bold text-gray-800 mb-4')
                    
                    # 时间信息
                    with ui.row().classes('items-center text-gray-500 mb-6'):
                        ui.icon('schedule', size='sm')
                        ui.label(f'发布时间: {post["created_at"]}').classes('ml-2')
                    
                    # 文章内容
                    content_lines = post['content'].split('\n')
                    with ui.column().classes('gap-4'):
                        for line in content_lines:
                            if line.strip():  # 只显示非空行
                                ui.label(line).classes('text-gray-700 leading-relaxed')
                
                # 操作按钮区域
                with ui.card().classes('w-full p-6 mb-8'):
                    ui.label('文章操作').classes('text-lg font-semibold text-gray-700 mb-4')
                    with ui.row().classes('gap-4'):
                        ui.button('✏️ 编辑文章', on_click=lambda: show_edit_post(post_id)).classes('bg-yellow-500 text-white hover:bg-yellow-600 px-6 py-3 rounded-lg')
                        
                        # 删除按钮
                        def delete_post():
                            def confirm_delete():
                                db.delete_post(post_id)
                                ui.notify('文章已删除', type='positive')
                                show_main_view()
                            
                            # 确认对话框
                            with ui.dialog() as dialog:
                                with ui.card().classes('p-6 w-96'):
                                    ui.icon('warning', color='red', size='xl').classes('mx-auto mb-4')
                                    ui.label('确认删除').classes('text-xl font-bold text-center mb-2')
                                    ui.label('确定要删除这篇文章吗?此操作不可恢复。').classes('text-gray-600 text-center mb-6')
                                    with ui.row().classes('justify-center gap-4'):
                                        ui.button('确定删除', on_click=lambda: [dialog.close(), confirm_delete()]).classes('bg-red-500 text-white hover:bg-red-600 px-4 py-2 rounded')
                                        ui.button('取消', on_click=dialog.close).classes('bg-gray-200 text-gray-700 hover:bg-gray-300 px-4 py-2 rounded')
                            dialog.open()
                        
                        ui.button('🗑️ 删除文章', on_click=delete_post).classes('bg-red-500 text-white hover:bg-red-600 px-6 py-3 rounded-lg')
                
                # 评论区域
                with ui.card().classes('w-full p-6'):
                    ui.label('💬 评论').classes('text-2xl font-bold text-gray-800 mb-6')
                    
                    # 添加评论表单
                    with ui.card().classes('bg-gray-50 p-6 mb-8'):
                        ui.label('添加新评论').classes('text-lg font-semibold text-gray-700 mb-4')
                        
                        with ui.grid(columns=1).classes('gap-4'):
                            comment_author = ui.input(placeholder='请输入您的名字').classes('w-full p-3 border rounded-lg focus:ring-2 focus:ring-blue-500')
                            comment_content = ui.textarea(placeholder='请输入评论内容...').classes('w-full h-32 p-3 border rounded-lg focus:ring-2 focus:ring-blue-500')
                        
                        def add_comment():
                            author = comment_author.value.strip()
                            content = comment_content.value.strip()
                            
                            if not author:
                                ui.notify('请输入名字', type='warning')
                                return
                            
                            if not content:
                                ui.notify('请输入评论内容', type='warning')
                                return
                            
                            try:
                                db.add_comment(post_id, author, content)
                                ui.notify('评论发表成功!', type='positive')
                                comment_author.value = ''
                                comment_content.value = ''
                                load_comments()
                            except Exception as e:
                                ui.notify(f'评论失败: {str(e)}', type='negative')
                        
                        ui.button('发表评论', on_click=add_comment).classes('bg-blue-500 text-white hover:bg-blue-600 px-6 py-2 rounded-lg mt-4')
                    
                    # 评论列表
                    comments_container = ui.column().classes('gap-4')
                    
                    def load_comments():
                        comments_container.clear()
                        comments = db.get_comments(post_id)
                        
                        if not comments:
                            with ui.card().classes('text-center p-8'):
                                ui.icon('chat', size='xl').classes('text-gray-400 mb-4')
                                ui.label('暂无评论').classes('text-gray-600')
                                ui.label('快来发表第一条评论吧!').classes('text-gray-500 text-sm')
                            return
                        
                        for comment in comments:
                            with comments_container:
                                with ui.card().classes('p-6'):
                                    # 评论头部
                                    with ui.row().classes('justify-between items-center mb-3'):
                                        with ui.row().classes('items-center'):
                                            ui.icon('person', color='blue', size='sm')
                                            ui.label(comment['author']).classes('font-bold text-gray-800 ml-2')
                                        ui.label(f'📅 {comment["created_at"]}').classes('text-sm text-gray-500')
                                    
                                    # 评论内容
                                    ui.label(comment['content']).classes('text-gray-700 ml-8 mt-2')
                    
                    # 初始加载评论
                    load_comments()
        
        # 初始显示主视图
        show_main_view()

# 创建界面
create_blog_ui()

# 运行应用
ui.run(title='📝 我的博客系统', port=8080, favicon='📝')

主要美化特性:

1. 布局美化

  • 使用 Tailwind CSS 类进行响应式布局
  • 居中容器,最大宽度限制
  • 卡片式设计,阴影效果
  • 网格和列布局

2. 颜色方案

  • 蓝色系主色调(标题、按钮)
  • 绿色表示创建/成功
  • 黄色表示编辑/警告
  • 红色表示删除/危险
  • 灰色用于背景和辅助信息

3. 组件美化

  • 按钮:圆角、悬停效果、内边距
  • 输入框:聚焦效果、圆角边框
  • 卡片:阴影、内边距、背景色
  • 图标:使用表情符号和图标增强视觉

4. 交互反馈

  • 按钮悬停效果
  • 输入框聚焦效果
  • 成功/警告/错误通知
  • 确认对话框美化

5. 实用CSS类

  • mx-auto my-8:居中布局
  • w-full max-w-6xl:响应式宽度
  • p-4 / p-6 / p-8:内边距
  • rounded-lg:圆角
  • shadow / hover:shadow-lg:阴影效果
  • bg-{color}-500:背景色
  • text-{color}-700:文字颜色
  • hover:bg-{color}-600:悬停效果

6. 图标和表情

  • 使用表情符号增强可读性
  • 适当使用图标组件
  • 统一视觉语言

这个美化版本保持了原有功能,但提供了更好的用户体验和视觉效果。所有样式都通过 .classes() 方法添加,没有使用 .style() 方法。

相关推荐
夏小花花1 小时前
<editor> 组件设置样式不生效问题
java·前端·vue.js·xss
weixin_307779131 小时前
Jenkins Ioncions API 插件:现代化图标库在持续集成中的应用
java·运维·开发语言·前端·jenkins
兔子零10241 小时前
零硬件交互:如何用纯前端把摄像头变成 4000 个粒子的魔法棒?
前端·算法
北辰alk1 小时前
Vue Router 组件内路由钩子全解析
前端·vue.js
天草二十六_简村人1 小时前
jenkins打包制作Python镜像,并推送至docker仓库,部署到k8s
后端·python·docker·容器·kubernetes·jenkins
克喵的水银蛇1 小时前
Flutter 弹性布局实战:Row/Column/Flex 核心用法与优化技巧
前端·javascript·typescript
辜月十1 小时前
Docker-Compose 【Mysql】
后端
悟空码字1 小时前
SpringBoot实现系统监控:给应用装上“健康手环”
java·后端·监控
GuluGuluWater1 小时前
受够了同事的垃圾代码?我用 Go 写了个自动审查工具
后端