feat: complete local version to overwrite remote

This commit is contained in:
DelLevin-Home
2026-06-16 03:30:57 +08:00
parent 1735c19f48
commit 3c78293f4d
129 changed files with 22814 additions and 0 deletions

287
www_comments/app.py Normal file
View File

@@ -0,0 +1,287 @@
from flask import Flask, request, jsonify, render_template, session, redirect, url_for
from flask_cors import CORS
import json
import os
from datetime import datetime
import hashlib
from config import *
app = Flask(__name__)
CORS(app) # 允许跨域请求
app.secret_key = SECRET_KEY
# 数据文件路径已在 config.py 中定义
# DATA_FILE = os.path.join(os.path.dirname(__file__), 'data', 'comments.json')
def read_comments():
"""读取评论数据"""
try:
if os.path.exists(DATA_FILE):
with open(DATA_FILE, 'r', encoding='utf-8') as f:
return json.load(f)
return {"comments": []}
except Exception as e:
print(f"读取数据失败: {e}")
return {"comments": []}
def save_comments(data):
"""保存评论数据"""
os.makedirs(os.path.dirname(DATA_FILE), exist_ok=True)
with open(DATA_FILE, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
def parse_user_agent(ua):
"""解析 User Agent 获取浏览器和系统信息"""
browser = 'Unknown'
os_name = 'Unknown'
# 浏览器检测
if 'Chrome' in ua and 'Edge' not in ua:
browser = 'Chrome'
elif 'Firefox' in ua:
browser = 'Firefox'
elif 'Safari' in ua and 'Chrome' not in ua:
browser = 'Safari'
elif 'Edge' in ua:
browser = 'Edge'
# 系统检测
if 'Windows' in ua:
os_name = 'Windows'
elif 'Mac' in ua:
os_name = 'macOS'
elif 'Linux' in ua:
os_name = 'Linux'
elif 'Android' in ua:
os_name = 'Android'
elif 'iPhone' in ua or 'iPad' in ua:
os_name = 'iOS'
return browser, os_name
@app.route('/api/comment', methods=['GET'])
def get_comments():
"""获取评论列表(前端展示用,仅返回已审核)"""
try:
page = int(request.args.get('page', 1))
page_size = int(request.args.get('pageSize', PAGE_SIZE_FRONTEND))
data = read_comments()
# 过滤已审核的评论
filtered = [c for c in data['comments']
if c.get('status') == 'approved']
# 按时间倒序排序
filtered.sort(key=lambda x: x.get('time', 0), reverse=True)
total_count = len(filtered)
total_pages = (total_count + page_size - 1) // page_size
# 分页
start = (page - 1) * page_size
end = start + page_size
paged_comments = filtered[start:end]
return jsonify({
'errno': 0,
'errmsg': '',
'data': {
'page': page,
'totalPages': total_pages,
'pageSize': page_size,
'count': total_count,
'data': paged_comments
}
})
except Exception as e:
return jsonify({
'errno': 1,
'errmsg': str(e)
}), 500
# 管理员账号配置已在 config.py 中定义
# ADMIN_USERNAME = 'admin'
# ADMIN_PASSWORD = 'zhaoyang0902'
def login_required(f):
"""登录验证装饰器"""
from functools import wraps
@wraps(f)
def decorated_function(*args, **kwargs):
if not session.get('logged_in'):
return redirect(url_for('login_page'))
return f(*args, **kwargs)
return decorated_function
@app.route('/login')
def login_page():
"""登录页面"""
return render_template('login.html')
@app.route('/api/login', methods=['POST'])
def do_login():
"""处理登录请求"""
data = request.get_json()
username = data.get('username')
password = data.get('password')
if username == ADMIN_USERNAME and password == ADMIN_PASSWORD:
session['logged_in'] = True
return jsonify({'errno': 0, 'errmsg': '登录成功'})
else:
return jsonify({'errno': 1, 'errmsg': '用户名或密码错误'}), 401
@app.route('/logout')
def logout():
"""退出登录"""
session.pop('logged_in', None)
return redirect(url_for('login_page'))
@app.route('/admin')
@login_required
def admin_page():
"""后台管理页面"""
return render_template('admin.html')
@app.route('/api/admin/comments', methods=['GET'])
@login_required
def get_admin_comments():
"""获取所有评论(后台管理用)"""
try:
status_filter = request.args.get('status', '')
keyword = request.args.get('keyword', '').lower()
page = int(request.args.get('page', 1))
page_size = int(request.args.get('pageSize', PAGE_SIZE_ADMIN))
data = read_comments()
comments = data['comments']
# 状态过滤
if status_filter:
comments = [c for c in comments if c.get('status') == status_filter]
else:
# 全部状态下默认不显示已删除的评论
comments = [c for c in comments if c.get('status') != 'deleted']
# 关键词搜索(昵称或内容)
if keyword:
comments = [c for c in comments if
keyword in c.get('nick', '').lower() or
keyword in c.get('comment', '').lower()]
# 按时间倒序排序
comments.sort(key=lambda x: x.get('time', 0), reverse=True)
total_count = len(comments)
total_pages = (total_count + page_size - 1) // page_size if total_count > 0 else 0
# 分页
start = (page - 1) * page_size
end = start + page_size
paged_comments = comments[start:end]
return jsonify({
'errno': 0,
'data': {
'list': paged_comments,
'total': total_count,
'page': page,
'pageSize': page_size,
'totalPages': total_pages
}
})
except Exception as e:
return jsonify({
'errno': 1,
'errmsg': str(e)
}), 500
@app.route('/api/admin/comment/<int:comment_id>', methods=['PUT'])
@login_required
def update_comment_status(comment_id):
"""更新评论状态"""
try:
update_data = request.get_json()
new_status = update_data.get('status')
if new_status not in ['approved', 'spam', 'deleted']:
return jsonify({'errno': 1, 'errmsg': '无效的状态'}), 400
data = read_comments()
found = False
for c in data['comments']:
if c['id'] == comment_id:
c['status'] = new_status
found = True
break
if not found:
return jsonify({'errno': 1, 'errmsg': '评论不存在'}), 404
save_comments(data)
return jsonify({'errno': 0, 'errmsg': '更新成功'})
except Exception as e:
return jsonify({
'errno': 1,
'errmsg': str(e)
}), 500
@app.route('/api/comment', methods=['POST'])
def add_comment():
"""添加评论"""
try:
comment_data = request.get_json()
if not comment_data:
return jsonify({
'errno': 1,
'errmsg': '无效的数据'
}), 400
data = read_comments()
# 生成新 ID
new_id = max([c.get('id', 0) for c in data['comments']], default=0) + 1
# 解析 User Agent
ua = comment_data.get('ua', '')
browser, os_name = parse_user_agent(ua)
# 生成头像(基于邮箱 MD5
email = comment_data.get('mail', '')
avatar_hash = hashlib.md5(email.encode('utf-8')).hexdigest()
avatar = f'https://seccdn.libravatar.org/avatar/{avatar_hash}'
# 创建新评论
new_comment = {
'id': new_id,
'nick': comment_data.get('nick', '匿名'),
'mail': comment_data.get('mail', ''),
'link': comment_data.get('link', ''),
'comment': f"<p>{comment_data.get('comment', '')}</p>\n",
'ua': ua,
'browser': browser,
'os': os_name,
'avatar': avatar,
'time': int(datetime.now().timestamp() * 1000),
'status': 'approved' # 直接审核通过
}
# 添加到数据中
data['comments'].append(new_comment)
save_comments(data)
return jsonify({
'errno': 0,
'errmsg': '',
'data': new_comment
})
except Exception as e:
return jsonify({
'errno': 1,
'errmsg': str(e)
}), 500
if __name__ == '__main__':
app.run(host=HOST, port=PORT, debug=DEBUG)