5分钟实现Web终端:FastUI命令行界面开发指南

5分钟实现Web终端:FastUI命令行界面开发指南

【免费下载链接】FastUI Build better UIs faster. 【免费下载链接】FastUI 项目地址: https://gitcode.com/GitHub_Trending/fa/FastUI

你还在为Web应用中嵌入终端界面发愁?传统方案需要复杂的WebSocket通信和前端状态管理,开发周期长达数周。本文将展示如何用FastUI在5分钟内构建一个交互式Web终端,支持命令输入、实时输出和历史记录功能,无需深入了解前端技术。

读完本文你将获得:

  • 用Python后端直接控制Web终端UI的能力
  • 实时数据流处理的SSE(Server-Sent Events,服务器发送事件)实现方案
  • 完整的终端组件代码,可直接集成到现有FastAPI项目

终端界面核心组件

FastUI提供了构建终端所需的全部基础组件,主要分布在以下文件中:

终端界面架构

终端模拟的核心是实现命令输入与输出流的双向通信。FastUI通过以下机制实现这一功能:

mermaid

实现步骤

1. 基础终端UI组件

创建文件 demo/terminal.py,实现终端界面的基础结构:

from fastapi import APIRouter, Request
from fastui import AnyComponent, FastUI
from fastui import components as c
from fastui.events import PageEvent, GoToEvent

from .shared import demo_page

router = APIRouter()

def terminal_component() -> list[AnyComponent]:
    return demo_page(
        c.PageTitle(text='FastUI Terminal'),
        c.Div(
            components=[
                # 终端输出区域
                c.Div(
                    class_name='terminal-output p-4 bg-gray-900 text-green-400 h-64 overflow-y-auto rounded-t-lg',
                    components=[
                        c.Text(text='FastUI Terminal v0.1\n'),
                        c.Text(text='>>> '),
                    ],
                    id='terminal-output'
                ),
                # 命令输入区域
                c.Form(
                    form_fields=[
                        c.FormFieldInput(
                            name='command',
                            html_type='text',
                            placeholder='输入命令并按回车...',
                            class_name='bg-gray-800 text-green-400 border-green-600 rounded-b-lg'
                        )
                    ],
                    submit_url='/terminal/exec',
                    method='POST',
                    submit_trigger=PageEvent(event='submit-command'),
                )
            ],
            class_name='w-full max-w-2xl mx-auto'
        )
    )

@router.get('/terminal', response_model=FastUI, response_model_exclude_none=True)
def terminal_page() -> list[AnyComponent]:
    return terminal_component()

2. 实现SSE实时输出

修改 demo/sse.py 文件,添加终端命令处理的SSE端点:

import asyncio
from collections.abc import AsyncIterable
from fastapi import APIRouter, Request
from fastapi.responses import StreamingResponse
from fastui import FastUI
from fastui import components as c

router = APIRouter()

async def command_execution_stream(command: str) -> AsyncIterable[str]:
    """模拟命令执行并流式输出结果"""
    yield f'data: {{"type":"Display","value":"Executing: {command}\\n"}}}\n\n'
    await asyncio.sleep(1)
    
    # 模拟命令输出
    outputs = [
        "Hello from FastUI Terminal!\n",
        "This is a simulated command output.\n",
        "You can replace this with real command execution.\n"
    ]
    
    for output in outputs:
        await asyncio.sleep(0.5)
        yield f'data: {{"type":"Display","value":"{output}"}}\n\n'
    
    yield f'data: {{"type":"Prompt","value":">>> "}}\n\n'

@router.post('/terminal/exec')
async def execute_command(request: Request) -> StreamingResponse:
    data = await request.form()
    command = data.get('command', '')
    return StreamingResponse(
        command_execution_stream(command),
        media_type='text/event-stream'
    )

3. 前端交互逻辑

创建文件 demo/static/terminal.js(需要在HTML模板中引入):

document.addEventListener('DOMContentLoaded', () => {
    const outputElement = document.getElementById('terminal-output');
    const commandInput = document.querySelector('input[name="command"]');
    
    // 监听表单提交
    document.querySelector('form').addEventListener('submit', (e) => {
        e.preventDefault();
        const command = commandInput.value;
        if (!command.trim()) return;
        
        // 添加命令到输出
        outputElement.appendChild(document.createTextNode(command + '\n'));
        commandInput.value = '';
        
        // 连接SSE流
        const eventSource = new EventSource(`/terminal/exec?command=${encodeURIComponent(command)}`);
        
        eventSource.onmessage = (event) => {
            const data = JSON.parse(event.data);
            const textNode = document.createTextNode(data.value);
            outputElement.appendChild(textNode);
            outputElement.scrollTop = outputElement.scrollHeight;
        };
        
        eventSource.onerror = () => eventSource.close();
    });
    
    // 允许通过回车提交命令
    commandInput.addEventListener('keydown', (e) => {
        if (e.key === 'Enter') {
            document.querySelector('form').dispatchEvent(new Event('submit'));
        }
    });
});

集成到主应用

修改 demo/main.py,添加终端路由:

# 在文件顶部导入
from .terminal import router as terminal_router

# 在router定义后添加
router.include_router(terminal_router, prefix='/terminal')

运行效果

启动demo应用后访问 /terminal 路径,你将看到类似下图的终端界面:

FastUI终端模拟界面

扩展功能

基于这个基础实现,你可以轻松添加更多功能:

完整的终端演示可以在 demo/main.py 中找到,更多组件示例见 demo/components_list.py

总结

本文展示了如何使用FastUI快速构建Web终端界面,通过结合FastUI的组件系统和SSE技术,我们实现了一个具有实时输出能力的命令行界面。这种方法避免了复杂的前端框架配置,让Python开发者可以专注于业务逻辑实现。

要进一步学习FastUI,可以参考以下资源:

如果你觉得这个终端实现有用,请点赞收藏本文,并关注获取更多FastUI使用技巧。下期我们将介绍如何实现终端命令的权限控制和审计日志功能。

【免费下载链接】FastUI Build better UIs faster. 【免费下载链接】FastUI 项目地址: https://gitcode.com/GitHub_Trending/fa/FastUI

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值