outsystem中文教程2025教你如何使用outsystem

outsystem中文教程2025
outsystem中文教程2025
outsystem中文教程2025

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>备忘录与待办事项管理</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            display: flex;
            min-height: 100vh;
        }

        /* 左侧菜单栏样式 */
        .sidebar {
            width: 200px;
            background-color: #f5f5f5;
            padding: 20px;
            border-right: 1px solid #e0e0e0;
        }

        .menu-item {
            padding: 10px 15px;
            margin-bottom: 5px;
            cursor: pointer;
            border-radius: 4px;
            transition: background-color 0.3s;
        }

        .menu-item:hover {
            background-color: #e0e0e0;
        }

        .menu-item.active {
            background-color: #007bff;
            color: white;
        }

        /* 右侧内容区样式 */
        .main-content {
            flex: 1;
            padding: 20px;
            background-color: #ffffff;
        }

        /* 顶部功能区样式 */
        .top-actions {
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 1px solid #e0e0e0;
        }

        .btn {
            padding: 8px 16px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            margin-right: 10px;
            transition: background-color 0.3s;
        }

        .btn:hover {
            background-color: #0056b3;
        }

        /* 内容区域样式 */
        .content-section {
            display: none;
        }

        .content-section.active {
            display: block;
        }

        /* 备忘录样式 */
        .memo-item {
            display: flex;
            align-items: center;
            margin-bottom: 10px;
            padding: 10px;
            border: 1px solid #e0e0e0;
            border-radius: 4px;
        }

        .memo-checkbox {
            width: 20px;
            height: 20px;
            border: 2px solid #007bff;
            border-radius: 50%;
            margin-right: 10px;
            cursor: pointer;
            position: relative;
        }

        .memo-checkbox.checked {
            background-color: #007bff;
        }

        .memo-checkbox.checked::after {
            content: '✓';
            color: white;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            font-size: 12px;
        }

        .memo-content {
            flex: 1;
        }

        .memo-content.completed {
            color: #888;
            text-decoration: line-through;
        }

        .memo-date {
            color: #666;
            font-size: 0.9em;
            margin-right: 10px;
        }

        .memo-delete {
            color: #dc3545;
            cursor: pointer;
            padding: 5px;
        }

        .memo-date-group {
            margin-bottom: 20px;
            border: 1px solid #e0e0e0;
            border-radius: 4px;
            padding: 10px;
        }

        .memo-date-title {
            color: #007bff;
            margin-bottom: 10px;
            padding-bottom: 5px;
            border-bottom: 1px solid #e0e0e0;
        }

        /* 待办事项区域样式 */
        .todo-container {
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            gap: 15px;
            margin-top: 20px;
        }

        .todo-section {
            border: 1px solid #e0e0e0;
            border-radius: 4px;
            padding: 15px;
        }

        .todo-section h3 {
            margin-bottom: 15px;
            color: #333;
        }

        .todo-item {
            background-color: #f8f9fa;
            border: 1px solid #dee2e6;
            border-radius: 4px;
            padding: 10px;
            margin-bottom: 10px;
            cursor: move;
            user-select: none;
        }

        .todo-items {
            min-height: 100px;
            background-color: #f8f9fa;
            border: 1px solid #dee2e6;
            border-radius: 4px;
            padding: 10px;
            margin-bottom: 10px;
        }

        .todo-items.dragover {
            background-color: #e9ecef;
            border: 2px dashed #007bff;
        }

        .todo-item-content {
            margin-bottom: 5px;
        }

        .todo-item-actions {
            display: flex;
            gap: 10px;
        }

        .todo-item-actions button {
            font-size: 0.8em;
            padding: 3px 8px;
        }

        .add-item {
            margin-top: 10px;
        }

        .add-item input[type="text"] {
            width: 400px;
            padding: 8px;
            font-size: 16px;
        }
        
        .add-item input[type="date"] {
            padding: 8px;
            font-size: 16px;
        }

        /* 添加响应式设计 */
        @media (max-width: 768px) {
            body {
                flex-direction: column;
            }
            .sidebar {
                width: 100%;
                border-right: none;
                border-bottom: 1px solid #e0e0e0;
            }
            .todo-container {
                grid-template-columns: 1fr;
            }
        }

        /* 添加打印样式 */
        @media print {
            .sidebar, .top-actions {
                display: none;
            }
            .main-content {
                padding: 0;
            }
            .memo-item, .todo-item {
                page-break-inside: avoid;
            }
        }

        /* 悬浮提示框样式 */
        .toast {
            position: fixed;
            top: 20px;
            left: 50%;
            transform: translateX(-50%);
            background-color: #28a745;
            color: white;
            padding: 15px 25px;
            border-radius: 4px;
            box-shadow: 0 2px 5px rgba(0,0,0,0.2);
            opacity: 0;
            z-index: 1000;
            transition: opacity 0.5s, transform 0.5s;
        }

        .toast.show {
            opacity: 1;
            transform: translate(-50%, 0);
        }

        .toast.hide {
            opacity: 0;
            transform: translate(-50%, -20px);
        }

        .toast.error {
            background-color: #dc3545;
        }
    </style>
</head>
<body>
    <!-- 左侧菜单栏 -->
    <div class="sidebar">
        <div class="menu-item active" data-section="memo">备忘录</div>
        <div class="menu-item" data-section="todo">待办事项</div>
    </div>

    <!-- 右侧内容区 -->
    <div class="main-content">
        <!-- 顶部功能区 -->
        <div class="top-actions">
            <div style="display: flex; align-items: center; gap: 10px;">
                <button class="btn" id="importBtn">导入数据</button>
                <button class="btn" id="exportBtn">导出数据</button>
                <div>
                    <input type="text" id="memosCsvPathInput" value="/Users/baidoufu/Desktop/memos.csv" readonly style="padding: 5px; border: 1px solid #ced4da; border-radius: 4px; width: 300px; background-color: #f8f9fa;">
                </div>
                <div>
                    <input type="text" id="todosCsvPathInput" value="/Users/baidoufu/Desktop/todos.csv" readonly style="padding: 5px; border: 1px solid #ced4da; border-radius: 4px; width: 300px; background-color: #f8f9fa;">
                </div>
                <div>
                    <input type="text" id="backupPathInput" value="/Users/baidoufu/Desktop/backup" readonly style="padding: 5px; border: 1px solid #ced4da; border-radius: 4px; width: 300px; background-color: #f8f9fa;">
                </div>
                <button class="btn" id="backupBtn">备份数据</button>
            </div>
        </div>

        <!-- 备忘录区域 -->
        <div class="content-section active" id="memo-section">
            <h2>备忘录</h2>
            <div class="add-item">
                <input type="text" id="newMemoInput" placeholder="输入新的备忘录内容" style="width: 500px; padding: 10px; font-size: 16px;">
                <input type="date" id="newMemoDate" value="" style="padding: 8px; font-size: 16px;">
                <button class="btn" onclick="addMemo()">添加</button>
            </div>
            <div id="memoList"></div>
        </div>

        <!-- 待办事项区域 -->
        <div class="content-section" id="todo-section">
            <div class="todo-header">
                <h2>待办事项</h2>
                <div class="add-item">
                    <input type="text" id="newTodoInput" placeholder="输入新的待办事项" style="width: 500px; padding: 10px; font-size: 16px;">
                    <button class="btn" onclick="addTodoItem('pending')">创建待办</button>
                </div>
            </div>
            <div class="todo-container">
                <div class="todo-section" id="todo-pending">
                    <h3>待办区</h3>
                    <div class="todo-items" ondrop="drop(event)" ondragover="allowDrop(event)" data-section="pending"></div>
                </div>
                <div class="todo-section" id="todo-inProgress">
                    <h3>进行区</h3>
                    <div class="todo-items" ondrop="drop(event)" ondragover="allowDrop(event)" data-section="inProgress"></div>
                </div>
                <div class="todo-section" id="todo-completed">
                    <h3>完成区</h3>
                    <div class="todo-items" ondrop="drop(event)" ondragover="allowDrop(event)" data-section="completed"></div>
                </div>
                <div class="todo-section" id="todo-onHold">
                    <h3>搁置区</h3>
                    <div class="todo-items" ondrop="drop(event)" ondragover="allowDrop(event)" data-section="onHold"></div>
                </div>
            </div>
        </div>
    </div>

    <script>
        // 数据存储
        let memos = [];
        let todos = {
            pending: [],
            inProgress: [],
            completed: [],
            onHold: []
        };

        // 菜单切换功能
        document.querySelectorAll('.menu-item').forEach(item => {
            item.addEventListener('click', () => {
                document.querySelectorAll('.menu-item').forEach(i => i.classList.remove('active'));
                document.querySelectorAll('.content-section').forEach(i => i.classList.remove('active'));
                
                item.classList.add('active');
                const section = item.dataset.section;
                document.getElementById(`${section}-section`).classList.add('active');
            });
        });

        // 初始化日期选择器默认值为今天
        document.getElementById('newMemoDate').valueAsDate = new Date();

        // 备忘录功能
        function addMemo() {
            const input = document.getElementById('newMemoInput');
            const dateInput = document.getElementById('newMemoDate');
            const content = input.value.trim();
            const selectedDate = dateInput.value;
            
            if (!content) {
                alert('请输入备忘录内容');
                return;
            }
            if (!selectedDate) {
                alert('请选择日期');
                return;
            }

            // 修复日期比较逻辑
            const selectedDateObj = new Date(selectedDate);
            const today = new Date();
            
            // 只比较年月日
            const isPastDate = selectedDateObj.getFullYear() < today.getFullYear() ||
                              (selectedDateObj.getFullYear() === today.getFullYear() && 
                               selectedDateObj.getMonth() < today.getMonth()) ||
                              (selectedDateObj.getFullYear() === today.getFullYear() && 
                               selectedDateObj.getMonth() === today.getMonth() && 
                               selectedDateObj.getDate() < today.getDate());

            if (isPastDate) {
                if (!confirm('您选择的日期是过去日期,确定要添加吗?')) {
                    return;
                }
            }

            const memo = {
                id: Date.now(),
                content: content,
                date: selectedDate,
                completed: false
            };
            memos.push(memo);
            renderMemos();
            input.value = '';
        }

        function renderMemos() {
            const memoList = document.getElementById('memoList');
            memoList.innerHTML = '';
            
            // 按日期对备忘录进行分组
            const groupedMemos = {};
            memos.forEach(memo => {
                if (!groupedMemos[memo.date]) {
                    groupedMemos[memo.date] = [];
                }
                groupedMemos[memo.date].push(memo);
            });
            
            // 按日期排序(从新到旧)
            const sortedDates = Object.keys(groupedMemos).sort((a, b) => new Date(b) - new Date(a));
            
            sortedDates.forEach(date => {
                // 检查该日期下的所有备忘录是否都已完成
                const allCompleted = groupedMemos[date].every(memo => memo.completed);
                
                // 如果该日期下的所有备忘录都已完成,则跳过渲染
                if (allCompleted) return;
                // 创建日期分组标题
                const dateGroup = document.createElement('div');
                dateGroup.className = 'memo-date-group';
                dateGroup.innerHTML = `<h3 class="memo-date-title">${date}</h3>`;
                memoList.appendChild(dateGroup);
                
                // 渲染该日期下的所有备忘录
                groupedMemos[date].forEach(memo => {
                    const memoElement = document.createElement('div');
                    memoElement.className = 'memo-item';
                    memoElement.innerHTML = `
                        <div class="memo-checkbox ${memo.completed ? 'checked' : ''}" onclick="toggleMemo(${memo.id})"></div>
                        <span class="memo-content ${memo.completed ? 'completed' : ''}">${memo.content}</span>
                        <span class="memo-delete" onclick="deleteMemo(${memo.id})">×</span>
                    `;
                    dateGroup.appendChild(memoElement);
                });
            });
        }

        function toggleMemo(id) {
            const memo = memos.find(m => m.id === id);
            if (memo) {
                memo.completed = !memo.completed;
                renderMemos();
            }
        }

        function deleteMemo(id) {
            memos = memos.filter(m => m.id !== id);
            renderMemos();
        }

        // 待办事项功能
        function addTodoItem(section) {
            const input = document.getElementById('newTodoInput');
            if (!input) return;
            const content = input.value.trim();
            if (content) {
                const todo = {
                    id: Date.now(),
                    content: content
                };
                todos[section].push(todo);
                renderTodos();
                input.value = '';
            }
        }

        function deleteTodoItem(section, id) {
            todos[section] = todos[section].filter(item => item.id !== id);
            renderTodos();
        }

        function moveTodoItem(id, fromSection, toSection) {
            const item = todos[fromSection].find(item => item.id === id);
            if (item) {
                todos[fromSection] = todos[fromSection].filter(i => i.id !== id);
                todos[toSection].push(item);
                renderTodos();
            }
        }

        function renderTodos() {
            Object.keys(todos).forEach(section => {
                const container = document.querySelector(`#todo-${section} .todo-items`);
                container.innerHTML = '';
                
                todos[section].forEach(todo => {
                    const todoElement = document.createElement('div');
                    todoElement.className = 'todo-item';
                    todoElement.draggable = true;
                    todoElement.setAttribute('data-id', todo.id);
                    todoElement.setAttribute('data-section', section);
                    todoElement.ondragstart = drag;
                    
                    todoElement.innerHTML = `
                        <div class="todo-item-content">${todo.content}</div>
                        <div class="todo-item-actions">
                            <button class="btn" style="background-color: #dc3545;" onclick="deleteTodoItem('${section}', ${todo.id})">删除</button>
                        </div>
                    `;
                    container.appendChild(todoElement);
                });
            });
        }

        function getSectionName(section) {
            const names = {
                pending: '待办区',
                inProgress: '进行区',
                completed: '完成区',
                onHold: '搁置区'
            };
            return names[section];
        }

        // 拖拽功能
        function allowDrop(event) {
            event.preventDefault();
            const dropTarget = event.target.closest('.todo-items');
            if (dropTarget) {
                dropTarget.classList.add('dragover');
            }
        }

        function drag(event) {
            const todoItem = event.target.closest('.todo-item');
            if (todoItem) {
                event.dataTransfer.setData('text/plain', JSON.stringify({
                    id: parseInt(todoItem.getAttribute('data-id')),
                    fromSection: todoItem.getAttribute('data-section')
                }));
            }
        }

        function drop(event) {
            event.preventDefault();
            const dropTarget = event.target.closest('.todo-items');
            if (!dropTarget) return;
            
            dropTarget.classList.remove('dragover');
            const data = JSON.parse(event.dataTransfer.getData('text/plain'));
            const toSection = dropTarget.dataset.section;
            
            if (data.fromSection !== toSection) {
                moveTodoItem(data.id, data.fromSection, toSection);
            }
        }

        // 添加拖拽结束时移除视觉效果
        document.querySelectorAll('.todo-items').forEach(container => {
            container.addEventListener('dragleave', (event) => {
                event.preventDefault();
                const dropTarget = event.target.closest('.todo-items');
                if (dropTarget) {
                    dropTarget.classList.remove('dragover');
                }
            });
        });

        // CSV导入导出功能
        document.getElementById('importBtn').addEventListener('click', async () => {
            try {
                const memosCsvPath = document.getElementById('memosCsvPathInput').value.trim();
                const todosCsvPath = document.getElementById('todosCsvPathInput').value.trim();

                // 读取memos.csv
                const memosResponse = await fetch('/read-files', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        memosCsvPath: memosCsvPath,
                        todosCsvPath: todosCsvPath
                    })
                });

                const data = await memosResponse.json();
                if (data.status === 'success') {
                    if (data.memosContent) {
                        importMemosFromCSV(data.memosContent);
                    }
                    if (data.todosContent) {
                        importTodosFromCSV(data.todosContent);
                    }
                    showToast('数据导入成功');
                } else {
                    throw new Error(data.error || '导入数据失败');
                }
            } catch (error) {
                showToast('导入数据失败: ' + error.message, 'error');
            }
        });

        document.getElementById('exportBtn').addEventListener('click', async () => {
            try {
                const memosCsvPath = document.getElementById('memosCsvPathInput').value.trim();
                const todosCsvPath = document.getElementById('todosCsvPathInput').value.trim();

                // 导出所有备忘录数据
                const memosCSV = generateMemosCSV(memos);
                await writeFile(memosCsvPath, memosCSV);

                // 导出所有待办事项数据
                const todosCSV = generateTodosCSV(todos);
                await writeFile(todosCsvPath, todosCSV);

                showToast('数据导出成功');
            } catch (error) {
                showToast('导出数据失败: ' + error.message, 'error');
            }
        });

        // 修改备份按钮点击事件处理
        document.getElementById('backupBtn').addEventListener('click', async () => {
            try {
                const backupPath = document.getElementById('backupPathInput').value.trim();
                
                // 获取当前时间戳
                const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
                
                // 备份备忘录数据
                const memosCSV = generateMemosCSV(memos);
                const memosBackupPath = `${backupPath}/memos_${timestamp}.csv`;
                await writeFile(memosBackupPath, memosCSV);

                // 备份待办事项数据
                const todosCSV = generateTodosCSV(todos);
                const todosBackupPath = `${backupPath}/todos_${timestamp}.csv`;
                await writeFile(todosBackupPath, todosCSV);

                showToast('数据备份成功');
            } catch (error) {
                showToast('备份数据失败: ' + error.message, 'error');
            }
        });

        function readFile(file) {
            return new Promise((resolve, reject) => {
                const reader = new FileReader();
                reader.onload = (e) => resolve(e.target.result);
                reader.onerror = (e) => reject(new Error('文件读取失败'));
                reader.readAsText(file);
            });
        }

        function writeFile(path, content) {
            return new Promise((resolve, reject) => {
                const xhr = new XMLHttpRequest();
                xhr.open('POST', '/export-data', true);
                xhr.setRequestHeader('Content-Type', 'application/json');
                xhr.onload = () => {
                    if (xhr.status === 200) {
                        resolve();
                    } else {
                        reject(new Error('文件写入失败'));
                    }
                };
                xhr.onerror = () => reject(new Error('网络错误'));
                xhr.send(JSON.stringify({
                    path: path,
                    content: content
                }));
            });
        }

        function generateMemosCSV(memosData) {
            let csv = 'id,content,date,completed\n';
            memosData.forEach(memo => {
                const content = memo.content.replace(/"/g, '""');
                csv += `${memo.id},"${content}",${memo.date},${memo.completed}\n`;
            });
            return csv;
        }

        function generateTodosCSV(todosData) {
            let csv = 'section,id,content\n';
            Object.entries(todosData).forEach(([section, items]) => {
                items.forEach(todo => {
                    const content = todo.content.replace(/"/g, '""');
                    csv += `${section},${todo.id},"${content}"\n`;
                });
            });
            return csv;
        }

        function importMemosFromCSV(csv) {
            const lines = csv.split('\n');
            if (lines.length < 2) {
                alert('CSV文件格式不正确');
                return;
            }
            memos = lines.slice(1).filter(line => line.trim()).map(line => {
                // 使用更精确的CSV解析方法
                const cols = line.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);
                if (cols.length < 4) return null;
                
                return {
                    id: parseInt(cols[0]),
                    content: cols[1].replace(/^"|"$/g, '').replace(/""/g, '"'),
                    date: cols[2],
                    completed: cols[3] === 'true'
                };
            }).filter(Boolean);
            renderMemos();
        }

        function importTodosFromCSV(csv) {
            const lines = csv.split('\n');
            if (lines.length < 2) return;

            Object.keys(todos).forEach(key => todos[key] = []);

            lines.slice(1).filter(line => line.trim()).forEach(line => {
                const cols = line.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);
                if (cols.length < 3) return;

                const section = cols[0];
                if (todos[section]) {
                    todos[section].push({
                        id: parseInt(cols[1]),
                        content: cols[2].replace(/^"|"$/g, '').replace(/""/g, '"')
                    });
                }
            });
            renderTodos();
        }

        function showToast(message, type = 'success') {
            // 移除所有现有的提示框
            document.querySelectorAll('.toast').forEach(toast => toast.remove());

            const toast = document.createElement('div');
            toast.className = `toast ${type}`;
            toast.textContent = message;
            document.body.appendChild(toast);

            // 显示提示框
            setTimeout(() => {
                toast.classList.add('show');
            }, 10);

            // 3秒后隐藏提示框
            setTimeout(() => {
                toast.classList.remove('show');
                toast.classList.add('hide');
                
                // 在动画结束后移除提示框
                toast.addEventListener('transitionend', () => {
                    if (toast.classList.contains('hide')) {
                        toast.remove();
                    }
                }, { once: true });
            }, 2000);
        }
    </script>
</body>
</html>
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
import os

class RequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/':
            try:
                with open('todo-page.html', 'rb') as f:
                    content = f.read()
                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                self.wfile.write(content)
            except:
                self.send_error(404, 'File not found')
        else:
            self.send_error(404, 'File not found')
    
    def do_POST(self):
        self.send_response(200)
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Access-Control-Allow-Methods', 'POST, OPTIONS')
        self.send_header('Access-Control-Allow-Headers', 'Content-Type')
        
        try:
            content_length = int(self.headers['Content-Length'])
            post_data = self.rfile.read(content_length)
            data = json.loads(post_data.decode('utf-8'))
            
            if self.path == '/export-data':
                path = data.get('path')
                content = data.get('content')
                
                # 检查路径和内容是否有效
                if not path or not content:
                    raise ValueError("Invalid request data")
                
                # 创建目录(如果不存在)
                os.makedirs(os.path.dirname(path), exist_ok=True)
                
                # 写入文件
                try:
                    with open(path, 'w', encoding='utf-8') as f:
                        f.write(content)
                    self.send_response(200)
                    self.send_header('Content-type', 'application/json')
                    self.end_headers()
                    self.wfile.write(json.dumps({'status': 'success'}).encode())
                except PermissionError:
                    self.send_response(403)
                    self.send_header('Content-type', 'application/json')
                    self.end_headers()
                    self.wfile.write(json.dumps({'error': 'Permission denied'}).encode())
                except Exception as e:
                    self.send_response(500)
                    self.send_header('Content-type', 'application/json')
                    self.end_headers()
                    self.wfile.write(json.dumps({'error': str(e)}).encode())
            elif self.path == '/read-files':
                memos_csv_path = data.get('memosCsvPath')
                todos_csv_path = data.get('todosCsvPath')
                
                response_data = {'status': 'success'}
                
                # 读取备忘录CSV文件
                if os.path.exists(memos_csv_path):
                    with open(memos_csv_path, 'r', encoding='utf-8') as f:
                        response_data['memosContent'] = f.read()
                
                # 读取待办事项CSV文件
                if os.path.exists(todos_csv_path):
                    with open(todos_csv_path, 'r', encoding='utf-8') as f:
                        response_data['todosContent'] = f.read()
                
                self.send_response(200)
                self.send_header('Content-type', 'application/json')
                self.end_headers()
                self.wfile.write(json.dumps(response_data).encode())
            else:
                self.send_error(404, 'Endpoint not found')
        except Exception as e:
            self.send_response(400)
            self.send_header('Content-type', 'application/json')
            self.end_headers()
            self.wfile.write(json.dumps({'error': str(e)}).encode())
    
    def do_OPTIONS(self):
        self.send_response(200)
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Access-Control-Allow-Methods', 'POST, OPTIONS')
        self.send_header('Access-Control-Allow-Headers', 'Content-Type')
        self.end_headers()

server = HTTPServer(('localhost', 8000), RequestHandler)
print("Server running on port 8000")
server.serve_forever()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值