功能模块: - 仪表盘: 用户统计、对话统计、方言使用分布 - 用户管理: 查看、搜索、删除用户 - 对话管理: 查看、删除对话、消息内容预览 - 数据导出: 导出用户数据 技术栈: - Flask + Tailwind CSS - RESTful API - 数据可视化
250 lines
7.0 KiB
Python
250 lines
7.0 KiB
Python
"""
|
|
方言版AI对话助手 - 后台管理系统
|
|
"""
|
|
|
|
from flask import Flask, render_template, jsonify, request, send_file
|
|
from flask_cors import CORS
|
|
import json
|
|
from pathlib import Path
|
|
from datetime import datetime
|
|
|
|
app = Flask(__name__)
|
|
CORS(app)
|
|
|
|
# 数据目录
|
|
DATA_DIR = Path(__file__).parent.parent / 'data'
|
|
USERS_FILE = DATA_DIR / 'users.json'
|
|
CHATS_FILE = DATA_DIR / 'chats.json'
|
|
|
|
def load_users():
|
|
if USERS_FILE.exists():
|
|
return json.loads(USERS_FILE.read_text(encoding='utf-8'))
|
|
return {}
|
|
|
|
def load_chats():
|
|
if CHATS_FILE.exists():
|
|
return json.loads(CHATS_FILE.read_text(encoding='utf-8'))
|
|
return {}
|
|
|
|
# ============ 页面路由 ============
|
|
|
|
@app.route('/')
|
|
def index():
|
|
return render_template('index.html')
|
|
|
|
@app.route('/users')
|
|
def users_page():
|
|
return render_template('users.html')
|
|
|
|
@app.route('/chats')
|
|
def chats_page():
|
|
return render_template('chats.html')
|
|
|
|
# ============ API路由 ============
|
|
|
|
@app.route('/api/stats')
|
|
def api_stats():
|
|
users = load_users()
|
|
chats = load_chats()
|
|
|
|
# 统计消息数
|
|
total_messages = 0
|
|
for chat in chats.values():
|
|
total_messages += len(chat.get('messages', []))
|
|
|
|
# 今日新增用户
|
|
today = datetime.now().strftime('%Y-%m-%d')
|
|
today_users = sum(1 for u in users.values() if u.get('created_at', '').startswith(today))
|
|
|
|
# 今日活跃对话
|
|
today_chats = sum(1 for c in chats.values() if c.get('updated_at', '').startswith(today))
|
|
|
|
return jsonify({
|
|
'users_count': len(users),
|
|
'chats_count': len(chats),
|
|
'messages_count': total_messages,
|
|
'today_users': today_users,
|
|
'today_chats': today_chats,
|
|
})
|
|
|
|
@app.route('/api/users')
|
|
def api_users():
|
|
users = load_users()
|
|
|
|
user_list = []
|
|
for uid, user in users.items():
|
|
user_list.append({
|
|
'id': uid,
|
|
'username': user.get('username', ''),
|
|
'phone': user.get('phone', ''),
|
|
'email': user.get('email', ''),
|
|
'chats_count': len(user.get('chats', [])),
|
|
'created_at': user.get('created_at', ''),
|
|
})
|
|
|
|
# 按创建时间倒序
|
|
user_list.sort(key=lambda x: x['created_at'], reverse=True)
|
|
|
|
return jsonify(user_list)
|
|
|
|
@app.route('/api/users/<user_id>')
|
|
def api_user_detail(user_id):
|
|
users = load_users()
|
|
chats = load_chats()
|
|
|
|
user = users.get(user_id)
|
|
if not user:
|
|
return jsonify({'error': '用户不存在'}), 404
|
|
|
|
# 获取用户的对话列表
|
|
user_chats = []
|
|
for chat_id in user.get('chats', []):
|
|
if chat_id in chats:
|
|
chat = chats[chat_id]
|
|
user_chats.append({
|
|
'id': chat_id,
|
|
'title': chat.get('title', ''),
|
|
'dialect': chat.get('dialect', ''),
|
|
'messages_count': len(chat.get('messages', [])),
|
|
'created_at': chat.get('created_at', ''),
|
|
})
|
|
|
|
return jsonify({
|
|
'user': {
|
|
'id': user_id,
|
|
'username': user.get('username', ''),
|
|
'phone': user.get('phone', ''),
|
|
'email': user.get('email', ''),
|
|
'created_at': user.get('created_at', ''),
|
|
},
|
|
'chats': user_chats
|
|
})
|
|
|
|
@app.route('/api/users/<user_id>', methods=['DELETE'])
|
|
def api_delete_user(user_id):
|
|
users = load_users()
|
|
chats = load_chats()
|
|
|
|
if user_id not in users:
|
|
return jsonify({'error': '用户不存在'}), 404
|
|
|
|
# 删除用户的所有对话
|
|
for chat_id in users[user_id].get('chats', []):
|
|
if chat_id in chats:
|
|
del chats[chat_id]
|
|
|
|
# 删除用户
|
|
del users[user_id]
|
|
|
|
USERS_FILE.write_text(json.dumps(users, ensure_ascii=False, indent=2), encoding='utf-8')
|
|
CHATS_FILE.write_text(json.dumps(chats, ensure_ascii=False, indent=2), encoding='utf-8')
|
|
|
|
return jsonify({'success': True})
|
|
|
|
@app.route('/api/chats')
|
|
def api_chats():
|
|
chats = load_chats()
|
|
users = load_users()
|
|
|
|
chat_list = []
|
|
for cid, chat in chats.items():
|
|
user = users.get(chat.get('user_id', ''), {})
|
|
chat_list.append({
|
|
'id': cid,
|
|
'title': chat.get('title', ''),
|
|
'dialect': chat.get('dialect', ''),
|
|
'user_name': user.get('username', '未知'),
|
|
'messages_count': len(chat.get('messages', [])),
|
|
'created_at': chat.get('created_at', ''),
|
|
'updated_at': chat.get('updated_at', ''),
|
|
})
|
|
|
|
# 按更新时间倒序
|
|
chat_list.sort(key=lambda x: x['updated_at'], reverse=True)
|
|
|
|
return jsonify(chat_list)
|
|
|
|
@app.route('/api/chats/<chat_id>')
|
|
def api_chat_detail(chat_id):
|
|
chats = load_chats()
|
|
users = load_users()
|
|
|
|
chat = chats.get(chat_id)
|
|
if not chat:
|
|
return jsonify({'error': '对话不存在'}), 404
|
|
|
|
user = users.get(chat.get('user_id', ''), {})
|
|
|
|
return jsonify({
|
|
'id': chat_id,
|
|
'title': chat.get('title', ''),
|
|
'dialect': chat.get('dialect', ''),
|
|
'user': {
|
|
'id': chat.get('user_id', ''),
|
|
'username': user.get('username', '未知'),
|
|
},
|
|
'messages': chat.get('messages', []),
|
|
'created_at': chat.get('created_at', ''),
|
|
'updated_at': chat.get('updated_at', ''),
|
|
})
|
|
|
|
@app.route('/api/chats/<chat_id>', methods=['DELETE'])
|
|
def api_delete_chat(chat_id):
|
|
chats = load_chats()
|
|
users = load_users()
|
|
|
|
if chat_id not in chats:
|
|
return jsonify({'error': '对话不存在'}), 404
|
|
|
|
user_id = chats[chat_id].get('user_id')
|
|
|
|
# 删除对话
|
|
del chats[chat_id]
|
|
|
|
# 从用户列表中移除
|
|
if user_id and user_id in users:
|
|
if chat_id in users[user_id].get('chats', []):
|
|
users[user_id]['chats'].remove(chat_id)
|
|
|
|
CHATS_FILE.write_text(json.dumps(chats, ensure_ascii=False, indent=2), encoding='utf-8')
|
|
USERS_FILE.write_text(json.dumps(users, ensure_ascii=False, indent=2), encoding='utf-8')
|
|
|
|
return jsonify({'success': True})
|
|
|
|
@app.route('/api/dialect-stats')
|
|
def api_dialect_stats():
|
|
"""方言使用统计"""
|
|
chats = load_chats()
|
|
|
|
dialect_counts = {}
|
|
for chat in chats.values():
|
|
dialect = chat.get('dialect', 'mandarin')
|
|
dialect_counts[dialect] = dialect_counts.get(dialect, 0) + 1
|
|
|
|
return jsonify(dialect_counts)
|
|
|
|
@app.route('/api/export/users')
|
|
def api_export_users():
|
|
"""导出用户数据"""
|
|
users = load_users()
|
|
# 隐藏密码
|
|
export_data = []
|
|
for uid, user in users.items():
|
|
export_data.append({
|
|
'id': uid,
|
|
'username': user.get('username', ''),
|
|
'phone': user.get('phone', ''),
|
|
'email': user.get('email', ''),
|
|
'created_at': user.get('created_at', ''),
|
|
'chats_count': len(user.get('chats', [])),
|
|
})
|
|
return jsonify(export_data)
|
|
|
|
if __name__ == '__main__':
|
|
print("=" * 50)
|
|
print("方言AI助手 - 后台管理系统")
|
|
print("=" * 50)
|
|
print(f"访问地址: http://localhost:19003")
|
|
print("=" * 50)
|
|
|
|
app.run(host='0.0.0.0', port=19003, debug=True) |