From 3aab712ff0c3663e88feb6b8615d2e51f3688ad2 Mon Sep 17 00:00:00 2001 From: hubian <908234780@qq.com> Date: Wed, 8 Apr 2026 12:16:21 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=90=8E=E5=8F=B0=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 功能模块: - 仪表盘: 用户统计、对话统计、方言使用分布 - 用户管理: 查看、搜索、删除用户 - 对话管理: 查看、删除对话、消息内容预览 - 数据导出: 导出用户数据 技术栈: - Flask + Tailwind CSS - RESTful API - 数据可视化 --- README.md | 7 ++ admin/app.py | 250 +++++++++++++++++++++++++++++++++++++ admin/templates/chats.html | 184 +++++++++++++++++++++++++++ admin/templates/index.html | 202 ++++++++++++++++++++++++++++++ admin/templates/users.html | 179 ++++++++++++++++++++++++++ 5 files changed, 822 insertions(+) create mode 100644 admin/app.py create mode 100644 admin/templates/chats.html create mode 100644 admin/templates/index.html create mode 100644 admin/templates/users.html diff --git a/README.md b/README.md index aca6ba0..12849f9 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,13 @@ API地址: http://192.168.2.5:1234/v1 ## 版本历史 +### v0.2.0 (2026-04-08) +- 新增后台管理系统 +- 用户管理(查看、删除) +- 对话管理(查看、删除) +- 统计仪表盘 +- 方言使用分布 + ### v0.1.0 (2026-04-08) - 初始版本 - 支持8种方言 diff --git a/admin/app.py b/admin/app.py new file mode 100644 index 0000000..b8a1973 --- /dev/null +++ b/admin/app.py @@ -0,0 +1,250 @@ +""" +方言版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/') +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/', 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/') +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/', 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) \ No newline at end of file diff --git a/admin/templates/chats.html b/admin/templates/chats.html new file mode 100644 index 0000000..88e2ed2 --- /dev/null +++ b/admin/templates/chats.html @@ -0,0 +1,184 @@ + + + + + + 对话管理 - 方言AI后台 + + + + +
+ + +
+

对话管理

+ + +
+ + + + + + + + + + + + + + +
标题用户方言消息数最后更新操作
加载中...
+
+ + + +
+
+ + + + \ No newline at end of file diff --git a/admin/templates/index.html b/admin/templates/index.html new file mode 100644 index 0000000..7917290 --- /dev/null +++ b/admin/templates/index.html @@ -0,0 +1,202 @@ + + + + + + 方言AI助手 - 后台管理 + + + + + +
+ + + + +
+ +
+
+
+
+

用户总数

+

-

+
+
+ +
+
+

今日新增: 0

+
+ +
+
+
+

对话总数

+

-

+
+
+ +
+
+

今日活跃: 0

+
+ +
+
+
+

消息总数

+

-

+
+
+ +
+
+
+ +
+
+
+

最热方言

+

-

+
+
+ +
+
+
+
+ + +
+
+

+ + 方言使用分布 +

+
+

加载中...

+
+
+ +
+

+ + 最近活跃用户 +

+
+

加载中...

+
+
+
+
+
+ + + + \ No newline at end of file diff --git a/admin/templates/users.html b/admin/templates/users.html new file mode 100644 index 0000000..940d673 --- /dev/null +++ b/admin/templates/users.html @@ -0,0 +1,179 @@ + + + + + + 用户管理 - 方言AI后台 + + + + +
+ + +
+
+

用户管理

+ +
+ + +
+ + + + + + + + + + + + + + +
用户名手机号邮箱对话数注册时间操作
加载中...
+
+ + + +
+
+ + + + \ No newline at end of file