关于 margin padding的一点感想

本文探讨了在网页布局中块级元素与内联元素的区别。重点介绍了padding与margin属性仅在块级元素上生效的特点,并解释了不同display属性值如inline、inline-block和block对这些样式的影响。

padding 与margin 只有在标签为快状时才会起作用 display inline不起作用  display inline-block 和block可以

from flask import Flask, render_template, request, jsonify, session import re import random import json from datetime import datetime import os import logging from typing import List, Dict, Any, Optional import sqlite3 from contextlib import contextmanager import bleach import secrets import hashlib app = Flask(__name__) app.secret_key = secrets.token_hex(32) # 日志配置 logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) class DatabaseManager: """数据库管理器""" def __init__(self, db_path='poems.db'): self.db_path = db_path self.init_db() def init_db(self): """初始化数据库""" with self.get_db_connection() as conn: # 创建诗词表 conn.execute(''' CREATE TABLE IF NOT EXISTS poems ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, author TEXT NOT NULL, content TEXT NOT NULL, type TEXT, tags TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ''') # 创建用户表 conn.execute(''' CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, password_hash TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ''') # 创建评论表 conn.execute(''' CREATE TABLE IF NOT EXISTS comments ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, poem_id INTEGER NOT NULL, content TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users (id), FOREIGN KEY (poem_id) REFERENCES poems (id) ) ''') # 创建点赞表 conn.execute(''' CREATE TABLE IF NOT EXISTS likes ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, poem_id INTEGER NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users (id), FOREIGN KEY (poem_id) REFERENCES poems (id), UNIQUE(user_id, poem_id) ) ''') # 创建索引 conn.execute('CREATE INDEX IF NOT EXISTS idx_poems_author ON poems(author)') conn.execute('CREATE INDEX IF NOT EXISTS idx_poems_type ON poems(type)') conn.execute('CREATE INDEX IF NOT EXISTS idx_comments_poem ON comments(poem_id)') conn.execute('CREATE INDEX IF NOT EXISTS idx_likes_poem ON likes(poem_id)') conn.commit() # 检查是否有数据 cursor = conn.execute('SELECT COUNT(*) FROM poems') count = cursor.fetchone()[0] if count == 0: # 添加示例数据 self.create_sample_data(conn) @contextmanager def get_db_connection(self): """数据库连接上下文管理器""" conn = sqlite3.connect(self.db_path) conn.row_factory = sqlite3.Row try: yield conn finally: conn.close() def create_sample_data(self, conn): """创建示例数据""" sample_poems = [ ('静夜思', '李白', '床前明月光,疑是地上霜。\n举头望明月,低头思故乡。', '五言绝句', '月亮,思乡'), ('春晓', '孟浩然', '春眠不觉晓,处处闻啼鸟。\n夜来风雨声,花落知多少。', '五言绝句', '春天,自然'), ('登鹳雀楼', '王之涣', '白日依山尽,黄河入海流。\n欲穷千里目,更上一层楼。', '五言绝句', '励志,哲理'), ('望庐山瀑布', '李白', '日照香炉生紫烟,遥看瀑布挂前川。\n飞流直下三千尺,疑是银河落九天。', '七言绝句', '瀑布,景色'), ('黄鹤楼送孟浩然之广陵', '李白', '故人西辞黄鹤楼,烟花三月下扬州。\n孤帆远影碧空尽,唯见长江天际流。', '七言绝句', '送别,友情') ] conn.executemany(''' INSERT INTO poems (title, author, content, type, tags) VALUES (?, ?, ?, ?, ?) ''', sample_poems) # 创建示例用户 conn.execute(''' INSERT INTO users (username, password_hash) VALUES (?, ?) ''', ('admin', hashlib.sha256('password123'.encode()).hexdigest())) conn.commit() def get_poem_by_id(self, poem_id: int) -> Optional[Dict[str, Any]]: """根据ID获取诗词""" with self.get_db_connection() as conn: cursor = conn.execute(''' SELECT p.*, (SELECT COUNT(*) FROM comments c WHERE c.poem_id = p.id) AS comment_count, (SELECT COUNT(*) FROM likes l WHERE l.poem_id = p.id) AS like_count FROM poems p WHERE p.id = ? ''', (poem_id,)) row = cursor.fetchone() return dict(row) if row else None def get_all_poems(self, page: int = 1, per_page: int = 12) -> tuple: """获取所有诗词(分页)""" offset = (page - 1) * per_page with self.get_db_connection() as conn: cursor = conn.execute(''' SELECT p.*, (SELECT COUNT(*) FROM comments c WHERE c.poem_id = p.id) AS comment_count, (SELECT COUNT(*) FROM likes l WHERE l.poem_id = p.id) AS like_count FROM poems p ORDER BY created_at DESC LIMIT ? OFFSET ? ''', (per_page, offset)) poems = [dict(row) for row in cursor.fetchall()] # 总数 cursor = conn.execute('SELECT COUNT(*) FROM poems') total_count = cursor.fetchone()[0] total_pages = (total_count + per_page - 1) // per_page return poems, total_pages def search_poems(self, query: str, page: int = 1, per_page: int = 12) -> tuple: """搜索诗词(分页)""" if not query: return self.get_all_poems(page, per_page) offset = (page - 1) * per_page search_term = f'%{query}%' with self.get_db_connection() as conn: cursor = conn.execute(''' SELECT p.*, (SELECT COUNT(*) FROM comments c WHERE c.poem_id = p.id) AS comment_count, (SELECT COUNT(*) FROM likes l WHERE l.poem_id = p.id) AS like_count FROM poems p WHERE title LIKE ? OR author LIKE ? OR content LIKE ? OR tags LIKE ? ORDER BY CASE WHEN title LIKE ? THEN 1 WHEN author LIKE ? THEN 2 WHEN content LIKE ? THEN 3 ELSE 4 END LIMIT ? OFFSET ? ''', (search_term, search_term, search_term, search_term, search_term, search_term, search_term, per_page, offset)) poems = [dict(row) for row in cursor.fetchall()] # 总数 cursor = conn.execute(''' SELECT COUNT(*) FROM poems WHERE title LIKE ? OR author LIKE ? OR content LIKE ? OR tags LIKE ? ''', (search_term, search_term, search_term, search_term)) total_count = cursor.fetchone()[0] total_pages = (total_count + per_page - 1) // per_page return poems, total_pages def get_all_authors(self) -> List[str]: """获取所有作者""" with self.get_db_connection() as conn: cursor = conn.execute('SELECT DISTINCT author FROM poems ORDER BY author') return [row['author'] for row in cursor.fetchall()] def get_all_types(self) -> List[str]: """获取所有类型""" with self.get_db_connection() as conn: cursor = conn.execute('SELECT DISTINCT type FROM poems ORDER BY type') return [row['type'] for row in cursor.fetchall()] def get_all_tags(self) -> List[str]: """获取所有标签""" with self.get_db_connection() as conn: cursor = conn.execute('SELECT tags FROM poems') all_tags = set() for row in cursor.fetchall(): if row['tags']: all_tags.update(tag.strip() for tag in row['tags'].split(',')) return sorted(list(all_tags)) def authenticate_user(self, username: str, password: str) -> Optional[Dict[str, Any]]: """验证用户""" password_hash = hashlib.sha256(password.encode()).hexdigest() with self.get_db_connection() as conn: cursor = conn.execute('SELECT * FROM users WHERE username = ? AND password_hash = ?', (username, password_hash)) user = cursor.fetchone() return dict(user) if user else None def register_user(self, username: str, password: str) -> bool: """注册用户""" password_hash = hashlib.sha256(password.encode()).hexdigest() with self.get_db_connection() as conn: try: conn.execute('INSERT INTO users (username, password_hash) VALUES (?, ?)', (username, password_hash)) conn.commit() return True except sqlite3.IntegrityError: return False # 用户名已存在 def add_comment(self, user_id: int, poem_id: int, content: str) -> bool: """添加评论""" clean_content = bleach.clean(content)[:500] with self.get_db_connection() as conn: try: conn.execute(''' INSERT INTO comments (user_id, poem_id, content) VALUES (?, ?, ?) ''', (user_id, poem_id, clean_content)) conn.commit() return True except sqlite3.Error: return False def get_comments_by_poem(self, poem_id: int, limit: int = 10) -> List[Dict[str, Any]]: """获取诗词的评论""" with self.get_db_connection() as conn: cursor = conn.execute(''' SELECT c.*, u.username, c.created_at FROM comments c JOIN users u ON c.user_id = u.id WHERE c.poem_id = ? ORDER BY c.created_at DESC LIMIT ? ''', (poem_id, limit)) return [dict(row) for row in cursor.fetchall()] def toggle_like(self, user_id: int, poem_id: int) -> bool: """切换点赞状态""" with self.get_db_connection() as conn: try: cursor = conn.execute('SELECT id FROM likes WHERE user_id = ? AND poem_id = ?', (user_id, poem_id)) existing = cursor.fetchone() if existing: conn.execute('DELETE FROM likes WHERE user_id = ? AND poem_id = ?', (user_id, poem_id)) else: conn.execute('INSERT INTO likes (user_id, poem_id) VALUES (?, ?)', (user_id, poem_id)) conn.commit() return True except sqlite3.Error: return False def get_like_status(self, user_id: int, poem_id: int) -> bool: """获取点赞状态""" with self.get_db_connection() as conn: cursor = conn.execute('SELECT id FROM likes WHERE user_id = ? AND poem_id = ?', (user_id, poem_id)) return cursor.fetchone() is not None def validate_input(input_str: str, max_len: int = 1000) -> str: """验证和清理输入""" if not input_str: return "" clean_input = bleach.clean(input_str)[:max_len] return clean_input.strip() def login_required(f): """登录验证装饰器""" from functools import wraps @wraps(f) def decorated_function(*args, **kwargs): if 'user_id' not in session: return '<script>alert("请先登录"); window.location="/login";</script>' return f(*args, **kwargs) return decorated_function # 初始化数据库 db_manager = DatabaseManager() @app.route('/') def index(): """首页""" page = request.args.get('page', 1, type=int) poems, total_pages = db_manager.get_all_poems(page) return f''' <!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> body {{ font-family: '楷体', serif; margin: 0; padding: 20px; background-color: #f8f9fa; }} .container {{ max-width: 1000px; margin: 0 auto; }} .header {{ text-align: center; margin-bottom: 30px; }} .poem-card {{ background: white; border-radius: 8px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }} .poem-title {{ font-size: 24px; color: #333; margin-bottom: 10px; }} .poem-author {{ color: #666; margin-bottom: 15px; }} .poem-content {{ white-space: pre-line; line-height: 1.8; }} .poem-meta {{ display: flex; gap: 15px; margin-top: 10px; color: #888; font-size: 14px; }} .pagination {{ display: flex; justify-content: center; margin-top: 30px; gap: 10px; }} .page-link {{ padding: 8px 15px; background: #007bff; color: white; text-decoration: none; border-radius: 4px; }} .page-link:hover {{ background: #0056b3; }} .nav {{ display: flex; justify-content: space-between; margin-bottom: 20px; }} .nav a {{ padding: 10px 15px; background: #28a745; color: white; text-decoration: none; border-radius: 4px; }} .nav a:hover {{ background: #218838; }} .stats {{ display: flex; gap: 15px; margin-top: 5px; font-size: 13px; color: #888; }} </style> </head> <body> <div class="container"> <div class="header"> <h1>古诗词鉴赏</h1> <div class="nav"> <a href="/">首页</a> <a href="/login">{session.get('username', '登录')}</a> </div> </div> <form method="get" action="/search" style="margin-bottom: 30px;"> <input type="text" name="q" placeholder="搜索诗词..." value="{request.args.get('q', '')}" style="width: 70%; padding: 10px; border: 1px solid #ddd; border-radius: 4px;"> <button type="submit" style="padding: 10px 20px; background: #007bff; color: white; border: none; border-radius: 4px;">搜索</button> </form> {''.join([ f''' <div class="poem-card"> <div class="poem-title">{poem['title']}</div> <div class="poem-author">{poem['author']}</div> <div class="poem-content">{poem['content']}</div> <div class="poem-meta"> <span>{poem['type']}</span> <span>{poem['tags']}</span> </div> <div class="stats"> <span>💬 {poem['comment_count']} 条评论</span> <span>👍 {poem['like_count']} 个赞</span> </div> <a href="/poem/{poem['id']}" style="display: inline-block; margin-top: 10px; padding: 8px 15px; background: #17a2b8; color: white; text-decoration: none; border-radius: 4px;">查看详情</a> </div> ''' for poem in poems ])} <div class="pagination"> {''.join([ f'<a class="page-link" href="?page={i}">{i}</a>' for i in range(1, total_pages + 1) ])} </div> </div> </body> </html> ''' @app.route('/search') def search(): """搜索页面""" query = request.args.get('q', '') page = request.args.get('page', 1, type=int) if query: poems, total_pages = db_manager.search_poems(validate_input(query), page) else: poems, total_pages = db_manager.get_all_poems(page) return f''' <!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> body {{ font-family: '楷体', serif; margin: 0; padding: 20px; background-color: #f8f9fa; }} .container {{ max-width: 1000px; margin: 0 auto; }} .header {{ text-align: center; margin-bottom: 30px; }} .poem-card {{ background: white; border-radius: 8px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }} .poem-title {{ font-size: 24px; color: #333; margin-bottom: 10px; }} .poem-author {{ color: #666; margin-bottom: 15px; }} .poem-content {{ white-space: pre-line; line-height: 1.8; }} .poem-meta {{ display: flex; gap: 15px; margin-top: 10px; color: #888; font-size: 14px; }} .pagination {{ display: flex; justify-content: center; margin-top: 30px; gap: 10px; }} .page-link {{ padding: 8px 15px; background: #007bff; color: white; text-decoration: none; border-radius: 4px; }} .page-link:hover {{ background: #0056b3; }} .nav {{ display: flex; justify-content: space-between; margin-bottom: 20px; }} .nav a {{ padding: 10px 15px; background: #28a745; color: white; text-decoration: none; border-radius: 4px; }} .nav a:hover {{ background: #218838; }} .stats {{ display: flex; gap: 15px; margin-top: 5px; font-size: 13px; color: #888; }} </style> </head> <body> <div class="container"> <div class="header"> <h1>搜索结果 - "{query}"</h1> <div class="nav"> <a href="/">首页</a> <a href="/login">{session.get('username', '登录')}</a> </div> </div> <form method="get" action="/search" style="margin-bottom: 30px;"> <input type="text" name="q" placeholder="搜索诗词..." value="{query}" style="width: 70%; padding: 10px; border: 1px solid #ddd; border-radius: 4px;"> <button type="submit" style="padding: 10px 20px; background: #007bff; color: white; border: none; border-radius: 4px;">搜索</button> </form> {''.join([ f''' <div class="poem-card"> <div class="poem-title">{poem['title']}</div> <div class="poem-author">{poem['author']}</div> <div class="poem-content">{poem['content']}</div> <div class="poem-meta"> <span>{poem['type']}</span> <span>{poem['tags']}</span> </div> <div class="stats"> <span>💬 {poem['comment_count']} 条评论</span> <span>👍 {poem['like_count']} 个赞</span> </div> <a href="/poem/{poem['id']}" style="display: inline-block; margin-top: 10px; padding: 8px 15px; background: #17a2b8; color: white; text-decoration: none; border-radius: 4px;">查看详情</a> </div> ''' for poem in poems ])} <div class="pagination"> {''.join([ f'<a class="page-link" href="?q={query}&page={i}">{i}</a>' for i in range(1, total_pages + 1) ])} </div> </div> </body> </html> ''' @app.route('/poem/<int:poem_id>') def poem_detail(poem_id): """诗词详情页面""" poem = db_manager.get_poem_by_id(poem_id) if not poem: return '<h1>诗词不存在</h1><a href="/">返回首页</a>' # 获取评论 comments = db_manager.get_comments_by_poem(poem_id) # 检查点赞状态 is_liked = False if 'user_id' in session: is_liked = db_manager.get_like_status(session['user_id'], poem_id) # 获取上一首和下一首 with db_manager.get_db_connection() as conn: cursor = conn.execute('SELECT id FROM poems ORDER BY id') all_ids = [row['id'] for row in cursor.fetchall()] try: current_index = all_ids.index(poem_id) prev_id = all_ids[current_index - 1] if current_index > 0 else None next_id = all_ids[current_index + 1] if current_index < len(all_ids) - 1 else None except ValueError: prev_id = next_id = None return f''' <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{poem['title']} - 古诗词鉴赏</title> <style> body {{ font-family: '楷体', serif; margin: 0; padding: 20px; background-color: #f8f9fa; }} .container {{ max-width: 800px; margin: 0 auto; }} .header {{ text-align: center; margin-bottom: 30px; }} .poem-detail {{ background: white; border-radius: 8px; padding: 30px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }} .poem-title {{ font-size: 28px; color: #333; margin-bottom: 10px; }} .poem-author {{ font-size: 20px; color: #666; margin-bottom: 20px; }} .poem-content {{ font-size: 18px; white-space: pre-line; line-height: 2; margin-bottom: 20px; }} .poem-meta {{ display: flex; gap: 15px; margin-bottom: 20px; color: #888; }} .nav-buttons {{ display: flex; justify-content: space-between; margin-bottom: 20px; }} .nav-btn {{ padding: 10px 20px; background: #007bff; color: white; text-decoration: none; border-radius: 4px; }} .nav-btn:hover {{ background: #0056b3; }} .nav-btn:disabled {{ background: #ccc; cursor: not-allowed; }} .social-actions {{ display: flex; gap: 15px; margin-bottom: 20px; }} .action-btn {{ padding: 10px 15px; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; }} .like-btn {{ background: #dc3545; color: white; }} .like-btn.active {{ background: #c82333; }} .comment-section {{ margin-top: 30px; }} .comment-form {{ margin-bottom: 20px; }} .comment-input {{ width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; resize: vertical; }} .comment-submit {{ margin-top: 10px; padding: 10px 20px; background: #28a745; color: white; border: none; border-radius: 4px; cursor: pointer; }} .comments-list {{ margin-top: 20px; }} .comment-item {{ padding: 15px; border-left: 3px solid #007bff; background: #f8f9fa; margin-bottom: 10px; }} .comment-header {{ display: flex; justify-content: space-between; margin-bottom: 5px; font-weight: bold; }} .comment-date {{ font-size: 12px; color: #888; }} .comment-content {{ line-height: 1.6; }} .login-prompt {{ padding: 15px; background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 4px; text-align: center; }} </style> </head> <body> <div class="container"> <div class="header"> <h1>古诗词鉴赏</h1> <div style="display: flex; justify-content: space-between; margin-top: 10px;"> <a href="/" style="padding: 10px 15px; background: #28a745; color: white; text-decoration: none; border-radius: 4px;">首页</a> <a href="/login" style="padding: 10px 15px; background: #17a2b8; color: white; text-decoration: none; border-radius: 4px;">{session.get('username', '登录')}</a> </div> </div> <div class="poem-detail"> <div class="poem-title">{poem['title']}</div> <div class="poem-author">{poem['author']}</div> <div class="poem-content">{poem['content']}</div> <div class="poem-meta"> <span>类型: {poem['type']}</span> <span>标签: {poem['tags']}</span> </div> <div class="nav-buttons"> <a href="/poem/{prev_id}" class="nav-btn" {'disabled' if not prev_id else ''}>上一首</a> <a href="/" class="nav-btn">返回列表</a> <a href="/poem/{next_id}" class="nav-btn" {'disabled' if not next_id else ''}>下一首</a> </div> <div class="social-actions"> <button class="action-btn like-btn {'active' if is_liked else ''}" onclick="toggleLike({poem_id}, this)"> 👍 赞 ({poem['like_count']}) </button> <span>💬 {poem['comment_count']} 条评论</span> </div> <div class="comment-section"> <h3>发表评论</h3> {'<div class="login-prompt">请先 <a href="/login" style="color: #007bff;">登录</a> 再发表评论</div>' if 'user_id' not in session else ''} <form class="comment-form" onsubmit="addComment(event, {poem_id})" style="{'display:none;' if 'user_id' not in session else ''}"> <textarea id="comment-input-{poem_id}" class="comment-input" rows="3" placeholder="写下你的感想..." required></textarea> <button type="submit" class="comment-submit">发布评论</button> </form> <div class="comments-list"> <h3>评论列表</h3> {''.join([ f''' <div class="comment-item"> <div class="comment-header"> <span>{comment['username']}</span> <span class="comment-date">{comment['created_at']}</span> </div> <div class="comment-content">{comment['content']}</div> </div> ''' for comment in comments ])} </div> </div> </div> </div> <script> async function toggleLike(poemId, button) {{ if (!sessionStorage.getItem('user_id')) {{ alert('请先登录'); window.location.href = '/login'; return; }} try {{ const response = await fetch('/api/likes', {{ method: 'POST', headers: {{ 'Content-Type': 'application/json' }}, body: JSON.stringify({{ poem_id: poemId }}) }}); const result = await response.json(); if (result.success) {{ const count = result.like_count || parseInt(button.textContent.match(/\d+/)[0]) + (button.classList.contains('active') ? -1 : 1); button.innerHTML = `👍 赞 (${count})`; button.classList.toggle('active'); }} else {{ alert(result.error || '操作失败'); }} }} catch (e) {{ console.error(e); alert('网络错误'); }} }} async function addComment(event, poemId) {{ event.preventDefault(); const input = document.getElementById(`comment-input-${{poemId}}`); const content = input.value.trim(); if (!content) return; try {{ const response = await fetch('/api/comments', {{ method: 'POST', headers: {{ 'Content-Type': 'application/json' }}, body: JSON.stringify({{ poem_id: poemId, content: content }}) }}); const result = await response.json(); if (result.success) {{ input.value = ''; location.reload(); // 简单刷新页面 }} else {{ alert(result.error || '评论失败'); }} }} catch (e) {{ console.error(e); alert('网络错误'); }} }} </script> </body> </html> ''' @app.route('/login', methods=['GET', 'POST']) def login(): """用户登录""" if request.method == 'POST': username = validate_input(request.form.get('username', '')) password = request.form.get('password', '') if not username or not password: return '<script>alert("请输入用户名和密码"); history.back();</script>' user = db_manager.authenticate_user(username, password) if user: session['user_id'] = user['id'] session['username'] = user['username'] return '<script>alert("登录成功"); window.location="/";</script>' else: return '<script>alert("用户名或密码错误"); history.back();</script>' return ''' <!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> body { font-family: '楷体', serif; margin: 0; padding: 20px; background-color: #f8f9fa; display: flex; justify-content: center; align-items: center; height: 100vh; } .login-container { background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); width: 400px; } .form-group { margin-bottom: 20px; } label { display: block; margin-bottom: 5px; font-weight: bold; } input[type="text"], input[type="password"] { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box; } button { width: 100%; padding: 12px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; } button:hover { background: #0056b3; } .back-link { display: block; text-align: center; margin-top: 15px; color: #007bff; text-decoration: none; } </style> </head> <body> <div class="login-container"> <h2 style="text-align: center; margin-bottom: 30px;">用户登录</h2> <form method="post"> <div class="form-group"> <label for="username">用户名</label> <input type="text" id="username" name="username" required> </div> <div class="form-group"> <label for="password">密码</label> <input type="password" id="password" name="password" required> </div> <button type="submit">登录</button> </form> <a href="/" class="back-link">返回首页</a> <p style="text-align: center; margin-top: 20px;">测试账号: admin / password123</p> </div> </body> </html> ''' @app.route('/api/comments', methods=['POST']) @login_required def api_add_comment(): """API: 添加评论""" data = request.json poem_id = data.get('poem_id') content = data.get('content') if not poem_id or not content: return jsonify({'success': False, 'error': '缺少参数'}), 400 success = db_manager.add_comment(session['user_id'], poem_id, content) return jsonify({'success': success}) @app.route('/api/likes', methods=['POST']) @login_required def api_toggle_like(): """API: 切换点赞""" data = request.json poem_id = data.get('poem_id') if not poem_id: return jsonify({'success': False, 'error': '缺少参数'}), 400 success = db_manager.toggle_like(session['user_id'], poem_id) if success: # 返回更新后的点赞状态和数量 is_liked = db_manager.get_like_status(session['user_id'], poem_id) poem = db_manager.get_poem_by_id(poem_id) return jsonify({ 'success': True, 'is_liked': is_liked, 'like_count': poem['like_count'] }) return jsonify({'success': False, 'error': '操作失败'}), 500 if __name__ == '__main__': app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 5000))) 打分
12-15
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值