Compare commits

...

44 Commits

Author SHA1 Message Date
60db170c0d fix: 添加获取用户信息的GET API路由 2026-04-28 13:09:13 +08:00
336e3cd12f fix: 登录用户换设备后头像同步,初始化从后台获取最新用户信息 2026-04-28 13:05:54 +08:00
f0d9ca09aa fix: init_db兼容旧数据库,自动添加缺失的系统配置字段 2026-04-28 12:57:33 +08:00
36801e9266 feat: 我的页面和关于页面绑定后台系统配置 2026-04-28 12:48:51 +08:00
5acd9f08f1 fix: 发现智能体搜索支持基础智能体 2026-04-28 11:04:28 +08:00
31732a6303 fix: 历史使用左边标题右边智能体名字 2026-04-28 10:57:57 +08:00
7f576827b0 fix: 历史使用记录左边智能体名字右边标题 2026-04-28 10:55:15 +08:00
8287be10ea feat: 智能体对话标题自动更新+历史显示优化 2026-04-28 10:49:33 +08:00
a56bad11f1 feat: 用户头像在对话界面正确显示 2026-04-28 09:13:49 +08:00
92c187d576 fix: 智能体对话界面不显示工具选择按钮 2026-04-28 00:09:58 +08:00
9eeeace88c fix: 工具选择状态记忆 + 过滤联网搜索 + 默认未启用 2026-04-27 23:56:36 +08:00
ba5d49005b feat: 添加更多工具按钮,支持多选工具 2026-04-27 23:44:37 +08:00
c71f27072a feat: 系统设置可配置版本信息、技术基础、开发者等 2026-04-27 23:32:37 +08:00
22a109d6c0 feat: 用户头像上传功能 2026-04-27 20:02:40 +08:00
0244715a8a fix: LLM和搜索调用时记录统计到backend 2026-04-27 18:50:33 +08:00
1c3f7604c9 feat: 后台管理添加查看用户对话记录功能 2026-04-27 18:38:44 +08:00
0086eaa1d6 feat: 智能体数据同步到backend + 初始化时从backend加载完整数据 2026-04-27 18:33:15 +08:00
8e17ef5e15 fix: 登录时保存完整用户数据 2026-04-27 18:20:49 +08:00
773fb89b01 fix: 对话创建和消息发送时同步到backend 2026-04-27 18:20:06 +08:00
8199773ef6 feat: 用户对话数据同步到backend + 用户资料修改同步 2026-04-27 18:06:55 +08:00
d153986f3d fix: 隐藏注册页面验证码功能(暂时跳过验证) 2026-04-27 17:56:46 +08:00
e9357577cb feat: 后台管理添加用户管理功能 + 前端用户注册登录调用backend API 2026-04-27 17:16:44 +08:00
24ba04b3e3 fix: 智能体历史使用记录只显示真正有对话的智能体 2026-04-27 17:03:50 +08:00
d1ddd340c0 fix: API地址改为相对路径,适应不同设备访问 2026-04-27 15:41:46 +08:00
6ab58cb363 fix: 发现页面条件判断缺少结尾 2026-04-27 15:31:06 +08:00
ba8d0ae679 feat: 前端APP智能体从后台配置加载
- 从后台API(/api/config)获取智能体列表
- 热门智能体 = tags中包含hot标签
- 其他类别 = 根据category字段分类(basic/work/study/life)
- 游客限制从后台配置加载
2026-04-27 15:13:21 +08:00
52d98e88c6 fix: 弹框添加滚动功能 2026-04-27 15:02:31 +08:00
25dff98583 fix: 修复admin.js语法错误 2026-04-27 14:41:06 +08:00
6452e4c976 fix: admin.js版本号更新 2026-04-27 14:33:57 +08:00
f85991064f feat: 智能体管理增加上线开关、标签、可使用工具
智能体新增功能:
- 上线开关(is_online):点击快速切换,未上线则APP不可见
- 标签(tags):支持多标签,逗号分隔(hot/popular/new等)
- 可使用工具(enable_tools):配置智能体可用的工具列表

类别调整:
- 热门改为标签,不再是类别
- 类别改为: basic/work/study/life
- hot=热门标签, popular=推荐标签, new=新品标签

数据库变更:
- agents表新增 is_online 字段
- agents表新增 enable_tools 字段
- 移除 enable_search 字段(改为工具)

API新增:
- /api/admin/agents/<id>/online 切换上线状态
- 前端配置只返回上线且活跃的智能体
2026-04-27 14:15:14 +08:00
c725aeb192 fix: 对话配置扁平化+启用联网搜索移到对话配置
对话配置改为单配置:
- 只有一个默认配置,所有用户共用
- 去掉添加/删除配置按钮和逻辑
- 直接编辑保存配置

配置参数扁平化:
- enable_search 启用联网搜索开关
- LLM配置、可用工具、历史记录数、Temperature、系统提示词

启用联网搜索开关:
- 从系统设置移到对话配置页面
- 开关自动添加/移除 search 工具

系统设置简化:
- 去掉启用联网搜索开关
- 提示用户去对话配置页面设置
2026-04-27 13:04:03 +08:00
423f3aa717 feat: 后台增加对话配置+工具配置管理
新增对话配置页面:
- 配置普通对话使用的LLM、可用工具
- 历史记录数、Temperature、系统提示词
- 支持多配置、设为默认

搜索配置改为工具配置:
- 工具类型: search/calculator/image/code/weather/custom
- 搜索作为工具之一管理
- 支持添加多种工具
- 工具配置: ID、名称、类型、提供商、API、Key、额外配置

API新增:
- /api/admin/chat - 对话配置CRUD
- /api/admin/tools - 工具配置CRUD
- /api/config 返回 tools 和 chat_config
2026-04-27 12:51:44 +08:00
2f60e30169 fix: 端口改为19021 2026-04-27 12:38:50 +08:00
4442d5056a fix: SQL语句错误修复 + 版本号更新 2026-04-27 12:35:24 +08:00
3411de1612 feat: 后台管理系统 (Python Flask)
后台管理功能:
- 大模型接口配置管理(增删改、设为默认)
- 智能体管理(增删改、类别、标签、prompt、LLM配置、热度等)
- 搜索配置管理(Tavily等搜索接口)
- 系统设置(应用名称、版本、游客限制、管理员密码)
- 统计信息(LLM调用、搜索调用、智能体使用排行)

技术方案:
- Python Flask 后端服务 (端口 19020)
- SQLite 数据库存储配置
- 前端后台管理界面 (/admin)
- RESTful API 接口

后台入口:
- URL: http://localhost:19020/admin
- 默认账号: admin / admin123

前端配置获取:
- /api/config 获取LLM、搜索、智能体、系统配置
2026-04-27 12:34:01 +08:00
f24cefb2ab fix: 设置页面返回按钮修复
- switchPage函数增加mainContent存在检查
- 如果当前页面不是主页结构,先调用showMainPage重建页面
- 确保从设置子页面返回能正确回到'我的'页面
2026-04-27 12:22:37 +08:00
cacdb09201 feat: 我的界面功能完善
用户编辑:
- 用户头像选择(15种预设头像)
- 用户名修改(唯一性检查)
- 个性签名
- 个人资料(手机号只读、邮箱、性别、年龄、地区)

消息通知:
- 通知开关、声音、震动设置
- 免打扰时段设置

隐私安全:
- 修改密码
- 账号信息查看
- 清除聊天记录
- 清除缓存
- 数据安全状态显示

帮助与反馈:
- 使用帮助指南
- 问题反馈表单
- 联系方式

关于:
- 版本信息
- 检查更新
- 隐私政策/用户协议入口
2026-04-27 11:50:16 +08:00
55902aa8b6 fix: 移除验证码功能(暂时隐藏)
- 移除验证码输入框和发送验证码按钮
- 移除验证码验证逻辑
- 保留手机号格式验证(11位中国手机号)
- 保留手机号唯一性检查
- 注册字段:用户名、手机号(必填)、邮箱(可选)、密码
2026-04-27 11:31:44 +08:00
295218b4e4 feat: 注册增加手机号验证和邮箱
- 手机号输入(必填,11位中国手机号格式验证)
- 验证码机制(模拟,6位随机码,5分钟有效期)
- 发送验证码按钮(60秒倒计时)
- 验证码输入框
- 邮箱输入(可选,格式验证)
- 手机号唯一性检查(防止重复注册)
2026-04-27 11:26:51 +08:00
0812a6192f fix: 普通对话返回后不再显示智能体对话
- showConversationList 简化为直接返回主页
- 主页对话列表正确过滤(只显示没有 agentId 的普通对话)
- 添加操作菜单支持(重命名、分享、置顶、删除)
- 统一使用全局变量 currentActionConvId
2026-04-27 11:18:15 +08:00
c8cea4c1a1 feat: 登录注册系统 + 游客使用限制
功能:
- 登录/注册界面(本地存储用户数据)
- 我的页面显示用户状态、登录/退出按钮
- 游客配额显示(对话会话/消息/智能体消息)

游客限制:
- 每天最多1个对话会话
- 每天最多20条对话消息
- 只能使用通用助手智能体
- 每天最多20条智能体消息
- 登录用户无限制

限制提示:
- 达到限制弹出提示对话框
- 提示登录解锁全部功能
2026-04-27 11:06:20 +08:00
439743c051 fix: 智能体对话不显示在历史对话列表中
- 对话页面只显示没有智能体的普通对话
- 智能体对话只在智能体页面的最近使用列表显示
- 搜索功能也只搜索普通对话
2026-04-27 10:50:43 +08:00
dbd1853e6e feat: 智能体发现和收藏功能
- 智能体界面顶部右侧添加搜索按钮(发现智能体)
- 点击进入发现页面,显示所有系统智能体
- 每个智能体显示简介、热度、类别
- 支持添加和收藏按钮
- 添加的智能体自动归类到对应类别
- 智能体界面顶部右侧添加收藏按钮(☆)
- 点击进入收藏夹页面,点击智能体进入对话
- 智能体长按弹出操作菜单(置顶、收藏、删除)
- 置顶、收藏、用户智能体配置持久化存储
2026-04-27 10:45:30 +08:00
213b11c707 feat: 智能体历史改为显示每次对话记录而非合并统计 2026-04-27 00:26:51 +08:00
9 changed files with 8119 additions and 419 deletions

12
.gitignore vendored Normal file
View File

@@ -0,0 +1,12 @@
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
*.so
*.egg-info/
dist/
build/
*.db
data.db
node_modules/

1406
backend/app.py Normal file

File diff suppressed because it is too large Load Diff

2
backend/requirements.txt Normal file
View File

@@ -0,0 +1,2 @@
flask>=2.0.0
flask-cors>=3.0.0

4
backend/start.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/bash
cd "$(dirname "$0")"
pip install -r requirements.txt -q
python app.py

482
www/admin.html Normal file
View File

@@ -0,0 +1,482 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI助手 - 后台管理</title>
<link rel="stylesheet" href="admin.css?v=3.6.6">
<style>
:root {
--primary: #667eea;
--primary-dark: #5a67d8;
--bg-color: #f5f7fa;
--card-bg: #ffffff;
--text-color: #2d3748;
--text-light: #718096;
--border-color: #e2e8f0;
--danger: #e53e3e;
--success: #22c55e;
--warning: #f59e0b;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--bg-color);
color: var(--text-color);
line-height: 1.6;
}
/* 登录页面 */
.login-page {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
background: linear-gradient(135deg, var(--primary) 0%, #764ba2 100%);
}
.login-card {
background: white;
padding: 40px;
border-radius: 16px;
width: 350px;
text-align: center;
}
.login-logo {
font-size: 48px;
margin-bottom: 16px;
}
.login-title {
font-size: 24px;
font-weight: 600;
margin-bottom: 24px;
}
.login-input {
width: 100%;
padding: 12px 16px;
border: 2px solid var(--border-color);
border-radius: 10px;
font-size: 16px;
margin-bottom: 16px;
outline: none;
}
.login-input:focus {
border-color: var(--primary);
}
.login-btn {
width: 100%;
padding: 14px;
background: linear-gradient(135deg, var(--primary) 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 10px;
font-size: 16px;
font-weight: 500;
cursor: pointer;
margin-top: 8px;
}
.login-btn:hover {
opacity: 0.9;
}
/* 主页面 */
.admin-page {
display: none;
}
.admin-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 24px;
background: white;
border-bottom: 1px solid var(--border-color);
}
.admin-logo {
display: flex;
align-items: center;
gap: 8px;
font-size: 20px;
font-weight: 600;
}
.admin-logo span {
font-size: 28px;
}
.admin-header-right {
display: flex;
align-items: center;
gap: 16px;
}
.admin-logout {
padding: 8px 16px;
background: var(--danger);
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
}
/* 侧边栏 */
.admin-container {
display: flex;
height: calc(100vh - 60px);
}
.admin-sidebar {
width: 220px;
background: white;
border-right: 1px solid var(--border-color);
padding: 16px;
}
.sidebar-item {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 16px;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s;
margin-bottom: 4px;
}
.sidebar-item:hover {
background: rgba(102, 126, 234, 0.1);
}
.sidebar-item.active {
background: linear-gradient(135deg, var(--primary) 0%, #764ba2 100%);
color: white;
}
.sidebar-icon {
font-size: 20px;
}
/* 内容区 */
.admin-content {
flex: 1;
padding: 24px;
overflow-y: auto;
}
.content-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
}
.content-title {
font-size: 24px;
font-weight: 600;
}
.add-btn {
padding: 10px 20px;
background: var(--primary);
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
}
/* 数据卡片 */
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
margin-bottom: 24px;
}
.stat-card {
background: white;
padding: 20px;
border-radius: 12px;
text-align: center;
}
.stat-icon {
font-size: 32px;
margin-bottom: 8px;
}
.stat-value {
font-size: 28px;
font-weight: 600;
color: var(--primary);
}
.stat-label {
font-size: 14px;
color: var(--text-light);
}
/* 数据表格 */
.data-table {
background: white;
border-radius: 12px;
overflow: hidden;
}
.data-table table {
width: 100%;
border-collapse: collapse;
}
.data-table th, .data-table td {
padding: 14px 16px;
text-align: left;
border-bottom: 1px solid var(--border-color);
}
.data-table th {
background: var(--bg-color);
font-weight: 600;
color: var(--text-light);
}
.data-table tr:last-child td {
border-bottom: none;
}
.data-table tr:hover td {
background: rgba(102, 126, 234, 0.05);
}
/* 操作按钮 */
.action-btns {
display: flex;
gap: 8px;
}
.action-btn {
padding: 6px 12px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 12px;
}
.action-btn.edit {
background: var(--primary);
color: white;
}
.action-btn.delete {
background: var(--danger);
color: white;
}
.action-btn.default {
background: var(--success);
color: white;
}
/* 默认标记 */
.default-badge {
padding: 4px 8px;
background: var(--success);
color: white;
border-radius: 4px;
font-size: 12px;
}
/* 模态框 */
.modal {
position: fixed;
inset: 0;
background: rgba(0,0,0,0.5);
display: none;
align-items: center;
justify-content: center;
z-index: 1000;
}
.modal.show {
display: flex;
}
.modal-content {
background: white;
padding: 24px;
border-radius: 16px;
max-width: 500px;
width: 90%;
max-height: 80vh;
overflow-y: auto;
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
}
.modal-title {
font-size: 20px;
font-weight: 600;
}
.modal-close {
font-size: 24px;
cursor: pointer;
color: var(--text-light);
}
.form-group {
margin-bottom: 16px;
}
.form-label {
display: block;
font-size: 14px;
font-weight: 500;
margin-bottom: 8px;
}
.form-input, .form-select, .form-textarea {
width: 100%;
padding: 12px;
border: 1px solid var(--border-color);
border-radius: 8px;
font-size: 14px;
outline: none;
}
.form-input:focus, .form-select:focus, .form-textarea:focus {
border-color: var(--primary);
}
.form-textarea {
resize: vertical;
min-height: 100px;
}
.form-submit {
width: 100%;
padding: 14px;
background: var(--primary);
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
cursor: pointer;
margin-top: 16px;
}
/* Toast */
.toast {
position: fixed;
top: 80px;
left: 50%;
transform: translateX(-50%);
background: var(--text-color);
color: white;
padding: 12px 24px;
border-radius: 8px;
font-size: 14px;
opacity: 0;
transition: opacity 0.3s;
z-index: 2000;
}
.toast.show {
opacity: 1;
}
</style>
</head>
<body>
<!-- 登录页面 -->
<div class="login-page" id="loginPage">
<div class="login-card">
<div class="login-logo">🤖</div>
<h1 class="login-title">后台管理系统</h1>
<input type="text" class="login-input" id="loginUsername" placeholder="用户名">
<input type="password" class="login-input" id="loginPassword" placeholder="密码">
<button class="login-btn" id="loginBtn">登录</button>
<p style="margin-top: 16px; color: #999; font-size: 12px;">默认: admin / admin123</p>
</div>
</div>
<!-- 管理页面 -->
<div class="admin-page" id="adminPage">
<header class="admin-header">
<div class="admin-logo">
<span>🤖</span>
AI助手 - 后台管理
</div>
<div class="admin-header-right">
<span id="adminName">管理员</span>
<button class="admin-logout" id="logoutBtn">退出</button>
</div>
</header>
<div class="admin-container">
<aside class="admin-sidebar">
<div class="sidebar-item active" data-page="stats">
<span class="sidebar-icon">📊</span>
<span>统计信息</span>
</div>
<div class="sidebar-item" data-page="users">
<span class="sidebar-icon">👥</span>
<span>用户管理</span>
</div>
<div class="sidebar-item" data-page="llm">
<span class="sidebar-icon">🧠</span>
<span>大模型配置</span>
</div>
<div class="sidebar-item" data-page="agents">
<span class="sidebar-icon">🤖</span>
<span>智能体管理</span>
</div>
<div class="sidebar-item" data-page="chat">
<span class="sidebar-icon">💬</span>
<span>对话配置</span>
</div>
<div class="sidebar-item" data-page="tools">
<span class="sidebar-icon">🔧</span>
<span>工具配置</span>
</div>
<div class="sidebar-item" data-page="system">
<span class="sidebar-icon">⚙️</span>
<span>系统设置</span>
</div>
</aside>
<main class="admin-content" id="mainContent">
<!-- 内容区动态加载 -->
</main>
</div>
</div>
<!-- Toast -->
<div class="toast" id="toast"></div>
<!-- 模态框 -->
<div class="modal" id="modal">
<div class="modal-content" id="modalContent">
<!-- 动态内容 -->
</div>
</div>
<script src="admin.js?v=3.6.6"></script>
</body>
</html>

1495
www/admin.js Normal file

File diff suppressed because it is too large Load Diff

3479
www/app.js

File diff suppressed because it is too large Load Diff

View File

@@ -8,12 +8,12 @@
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<title>AI助手</title>
<link rel="stylesheet" href="style.css?v=3.1.2">
<link rel="stylesheet" href="style.css?v=3.5.1">
<link rel="manifest" href="manifest.json">
</head>
<body>
<div id="app"></div>
<script src="marked.min.js?v=3.1.2"></script>
<script src="app.js?v=3.1.2"></script>
<script src="marked.min.js?v=3.5.1"></script>
<script src="app.js?v=3.5.1"></script>
</body>
</html>

File diff suppressed because it is too large Load Diff