Skip to content

Commit

Permalink
修复Markdown渲染、举报无效果、点赞不正常显示的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
virgil698 authored Feb 26, 2025
1 parent 841c2ef commit aa6e82e
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 68 deletions.
104 changes: 51 additions & 53 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
from flask_wtf.csrf import CSRFProtect
import re

from bleach import clean
from bs4 import BeautifulSoup
from html_sanitizer import Sanitizer

app = Flask(__name__, template_folder='templates')
app.secret_key = os.getenv("SECRET_KEY", "your_secret_key_should_be_complex")
Expand Down Expand Up @@ -100,17 +100,16 @@ def initialize_database(app):

# Markdown转换 + XSS过滤
def convert_markdown_to_html(markdown_text):
# 使用 markdown 库的安全模式
html = markdown.markdown(markdown_text, safe_mode='escape')
# 使用 markdown 库将 Markdown 转换为 HTML
html = markdown.markdown(markdown_text)

# 定义允许的标签和属性
# 使用 bleach 清洗 HTML
allowed_tags = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'pre', 'hr', 'br', 'div',
'span', 'ul', 'ol', 'li', 'strong', 'em', 'code', 'blockquote',
'a', 'img', 'table', 'thead', 'tbody', 'tr', 'th', 'td']
allowed_attributes = {
'a': ['href', 'title', 'target'],
'img': ['src', 'alt', 'width', 'height'],
'*': ['class', 'style'],
'div': ['class', 'style'],
'span': ['class', 'style'],
'table': ['class', 'style'],
Expand All @@ -122,12 +121,12 @@ def convert_markdown_to_html(markdown_text):
'blockquote': ['class', 'style']
}

# 使用 html-sanitizer 进行清理
sanitizer = Sanitizer(
sanitized_html = clean(
html,
tags=allowed_tags,
attributes=allowed_attributes
attributes=allowed_attributes,
strip=True
)
sanitized_html = sanitizer.sanitize(html)

# 使用 BeautifulSoup 再次清理和一致化
soup = BeautifulSoup(sanitized_html, 'html.parser')
Expand All @@ -138,13 +137,13 @@ def convert_markdown_to_html(markdown_text):

def remove_markdown(text):
text = re.sub(r'\*\*', '', text) # 去除粗体
text = re.sub(r'\*', '', text) # 去除斜体
text = re.sub(r'`', '', text) # 去除代码块
text = re.sub(r'#', '', text) # 去除标题
text = re.sub(r'\*', '', text) # 去除斜体
text = re.sub(r'`', '', text) # 去除代码块
text = re.sub(r'#', '', text) # 去除标题
text = re.sub(r'\n-{3,}', '', text) # 去除水平线
text = re.sub(r'\n={3,}', '', text) # 去除水平线
text = re.sub(r'\n\* \n', '', text) # 去除列表
text = re.sub(r'\n\d\.', '', text) # 去除有序列表
text = re.sub(r'\n\d\.', '', text) # 去除有序列表
text = re.sub(r'!\[.*?\]\(.*?\)', '', text) # 去除图片
return text

Expand All @@ -160,7 +159,7 @@ def before_request():
return redirect(url_for('install'))

if 'user_id' in session:
user = User.query.get(session['user_id'])
user = db.session.get(User, session['user_id'])
if user:
g.user = user
g.role = user.role
Expand Down Expand Up @@ -316,7 +315,6 @@ def view_post(post_id):
flash('评论添加成功!', 'success')
return redirect(url_for('view_post', post_id=post.id))

# 使用 SQLAlchemy 的 ORM 查询过滤评论
comments = db.session.query(Comment).filter(
Comment.post_id == post.id,
Comment.deleted == False
Expand All @@ -340,7 +338,7 @@ def report_post(post_id):
if not g.user:
return jsonify({'success': False, 'message': '请登录后再进行举报'}), 403

reason = request.form.get('reason', '')
reason = request.json.get('reason', '')
if not reason:
return jsonify({'success': False, 'message': '举报原因不能为空'}), 400

Expand All @@ -359,7 +357,7 @@ def report_comment(comment_id):
if not g.user:
return jsonify({'success': False, 'message': '请登录后再进行举报'}), 403

reason = request.form.get('reason', '')
reason = request.json.get('reason', '')
if not reason:
return jsonify({'success': False, 'message': '举报原因不能为空'}), 400

Expand All @@ -373,6 +371,42 @@ def report_comment(comment_id):
return jsonify({'success': True, 'message': '举报成功!'}), 200


@app.route('/like_post/<int:post_id>', methods=['POST'])
def like_post(post_id):
if not g.user:
return jsonify({'success': False, 'message': '未登录'})

existing_like = Like.query.filter_by(user_id=g.user.id, post_id=post_id).first()
if existing_like:
return jsonify({'success': False, 'message': '您已经点过赞了'})

new_like = Like(user_id=g.user.id, post_id=post_id)
db.session.add(new_like)
db.session.query(Post).filter_by(id=post_id).update({'like_count': Post.like_count + 1})
db.session.commit()

post = db.session.get(Post, post_id)
return jsonify({'success': True, 'like_count': post.like_count})


@app.route('/like_comment/<int:comment_id>', methods=['POST'])
def like_comment(comment_id):
if not g.user:
return jsonify({'success': False, 'message': '未登录'})

existing_like = Like.query.filter_by(user_id=g.user.id, comment_id=comment_id).first()
if existing_like:
return jsonify({'success': False, 'message': '您已经点过赞了'})

new_like = Like(user_id=g.user.id, comment_id=comment_id)
db.session.add(new_like)
db.session.query(Comment).filter_by(id=comment_id).update({'like_count': Comment.like_count + 1})
db.session.commit()

comment = db.session.get(Comment, comment_id)
return jsonify({'success': True, 'like_count': comment.like_count})


@app.route('/upgrade_user/<int:user_id>')
def upgrade_user(user_id):
if g.role != 'admin':
Expand Down Expand Up @@ -436,42 +470,6 @@ def handle_report(report_id):
return jsonify({'success': True, 'message': '未违规,举报已关闭'})


@app.route('/like_post/<int:post_id>', methods=['POST'])
def like_post(post_id):
if not g.user:
return jsonify({'success': False, 'message': '未登录'})

existing_like = Like.query.filter_by(user_id=g.user.id, post_id=post_id).first()
if existing_like:
return jsonify({'success': False, 'message': '您已经点过赞了'})

new_like = Like(user_id=g.user.id, post_id=post_id)
db.session.add(new_like)
db.session.query(Post).filter_by(id=post_id).update({'like_count': Post.like_count + 1})
db.session.commit()

post = Post.query.get(post_id)
return jsonify({'success': True, 'like_count': post.like_count})


@app.route('/like_comment/<int:comment_id>', methods=['POST'])
def like_comment(comment_id):
if not g.user:
return jsonify({'success': False, 'message': '未登录'})

existing_like = Like.query.filter_by(user_id=g.user.id, comment_id=comment_id).first()
if existing_like:
return jsonify({'success': False, 'message': '您已经点过赞了'})

new_like = Like(user_id=g.user.id, comment_id=comment_id)
db.session.add(new_like)
db.session.query(Comment).filter_by(id=comment_id).update({'like_count': Comment.like_count + 1})
db.session.commit()

comment = Comment.query.get(comment_id)
return jsonify({'success': True, 'like_count': comment.like_count})


if __name__ == '__main__':
config = get_config()
initialize_database(app)
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ html-sanitizer~=2.5.0
lxml~=5.3.1
lxml-html-clean~=0.4.1
soupsieve~=2.6
bleach~=6.2.0
19 changes: 18 additions & 1 deletion templates/admin_panel.html
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,24 @@ <h5 class="text-center">管理举报</h5>
return;
}
if (confirm('确定要处理该举报吗?')) {
window.location.href = `/handle_report/${reportId}?status=${status}`;
fetch(`/handle_report/${reportId}`, {
method: 'POST',
headers: {
'X-CSRFToken': '{{ csrf_token() }}',
'Content-Type': 'application/json'
},
body: JSON.stringify({ status: status })
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert(data.message);
location.reload(); // 刷新页面以更新举报状态
} else {
alert(data.message);
}
})
.catch(error => console.error('Error:', error));
}
}
</script>
Expand Down
123 changes: 109 additions & 14 deletions templates/view_post.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@
max-width: 100%;
height: auto;
}

.like-count {
color: #2AFD6D;
}

.comment-like-count {
color: #FFF120; /* 金黄色 */
font-weight: bold;
}
</style>
{% endblock %}

Expand Down Expand Up @@ -70,11 +79,14 @@ <h5 class="card-title">评论</h5>
{% if not comment.deleted %}
<div class="media mb-4">
<div class="media-body">
<h6 class="mt-0">{{ comment.author.username }} 说:</h6>
<div class="d-flex justify-content-between align-items-center">
<h6 class="mt-0">{{ comment.author.username }} 说:</h6>
<span class="text-success comment-like-count">点赞: {{ comment.like_count }}</span>
</div>
<div class="markdown-content">
{{ comment.html_content | safe }}
</div>
<div class="d-flex justify-content-between align-items-center">
<div class="d-flex justify-content-between align-items-center mt-2">
{% if g.user %}
<a href="#" class="btn btn-success btn-sm" onclick="incrementLikeComment('{{ comment.id }}')">
<i class="fas fa-thumbs-up"></i> 点赞
Expand Down Expand Up @@ -106,19 +118,102 @@ <h6 class="mt-0">{{ comment.author.username }} 说:</h6>
</div>

<script>
document.addEventListener('DOMContentLoaded', function() {
window.Prism = window.Prism || {};
window.Prism.manual = true;
Prism.highlightAll();
// 定义点赞函数
function incrementLike(postId) {
fetch(`/like_post/${postId}`, {
method: 'POST',
headers: {
'X-CSRFToken': '{{ csrf_token() }}',
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
// 更新点赞计数
const likeCountElement = document.querySelector('.like-count');
likeCountElement.textContent = `点赞: ${data.like_count}`;
} else {
alert(data.message);
}
})
.catch(error => console.error('Error:', error));
}

// 定义举报帖子函数
function reportPost(postId) {
const reason = prompt('请输入举报原因');
if (!reason) {
alert('举报原因不能为空');
return;
}

document.querySelectorAll('.markdown-content a').forEach(link => {
if (link.href && !link.href.startsWith(window.location.origin)) {
link.target = '_blank';
link.rel = 'noopener noreferrer';
}
});
});
fetch(`/report_post/${postId}`, {
method: 'POST',
headers: {
'X-CSRFToken': '{{ csrf_token() }}',
'Content-Type': 'application/json'
},
body: JSON.stringify({ reason })
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert(data.message);
} else {
alert(data.message);
}
})
.catch(error => console.error('Error:', error));
}

// 定义评论点赞函数
function incrementLikeComment(commentId) {
fetch(`/like_comment/${commentId}`, {
method: 'POST',
headers: {
'X-CSRFToken': '{{ csrf_token() }}',
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
// 更新评论的点赞计数
const likeCountElement = document.querySelector(`.comment-like-count-${commentId}`);
likeCountElement.textContent = `点赞: ${data.like_count}`;
} else {
alert(data.message);
}
})
.catch(error => console.error('Error:', error));
}

// 定义举报评论函数
function reportComment(commentId) {
const reason = prompt('请输入举报原因');
if (!reason) {
alert('举报原因不能为空');
return;
}

// JavaScript 函数保持不变
fetch(`/report_comment/${commentId}`, {
method: 'POST',
headers: {
'X-CSRFToken': '{{ csrf_token() }}',
'Content-Type': 'application/json'
},
body: JSON.stringify({ reason })
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert(data.message);
} else {
alert(data.message);
}
})
.catch(error => console.error('Error:', error));
}
</script>
{% endblock %}

0 comments on commit aa6e82e

Please sign in to comment.