完善项目结构

This commit is contained in:
zhinianboke 2025-07-24 14:16:18 +08:00
parent c8150ae464
commit 9ec01047aa
33 changed files with 2692 additions and 2212 deletions

View File

@ -70,6 +70,22 @@ TOKEN_RETRY_INTERVAL=300
# 消息过期时间 (毫秒)
MESSAGE_EXPIRE_TIME=300000
# ==================== AI回复配置 ====================
# AI回复功能总开关 (true/false)
AI_REPLY_ENABLED=false
# 默认AI模型
DEFAULT_AI_MODEL=qwen-plus
# 默认AI API地址
DEFAULT_AI_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
# AI请求超时时间 (秒)
AI_REQUEST_TIMEOUT=30
# AI最大生成token数
AI_MAX_TOKENS=100
# ================================
# 自动回复配置
# ================================

3
.gitignore vendored
View File

@ -27,4 +27,5 @@ __pypackages__/
venv/
ENV/
env.bak/
venv.bak/
venv.bak/
*.db

214
AI_REPLY_GUIDE.md Normal file
View File

@ -0,0 +1,214 @@
# 🤖 AI回复功能使用指南
## 📋 功能概述
AI回复功能集成了先进的人工智能技术为每个闲鱼账号提供智能化的客服回复能力。系统支持意图识别、智能议价、技术咨询等多种场景让您的客服更加专业和高效。
## ✨ 核心特性
### 🎯 智能意图识别
- **价格咨询**: 自动识别议价、优惠、降价等价格相关询问
- **技术咨询**: 识别产品参数、使用方法、故障等技术问题
- **通用咨询**: 处理商品介绍、物流、售后等常见问题
### 💰 智能议价系统
- **阶梯式降价**: 根据议价轮数智能调整优惠幅度
- **价值强调**: 突出商品优势,提高成交率
- **议价限制**: 可设置最大优惠百分比和金额
### 🧠 多Agent专家系统
- **分类Agent**: 负责意图识别和路由
- **价格Agent**: 专业的议价专家
- **技术Agent**: 产品技术支持专家
- **默认Agent**: 通用客服助手
### 📝 上下文感知
- **对话历史**: 记住完整的对话上下文
- **商品信息**: 结合具体商品信息回复
- **个性化**: 根据用户行为调整回复策略
## 🚀 快速开始
### 1. 启用AI回复
1. **进入账号管理页面**
2. **找到目标账号**,点击 🤖 **配置AI回复** 按钮
3. **开启AI回复开关**
4. **配置API密钥**
### 2. 配置API密钥
#### 通义千问 (推荐)
```
模型: qwen-plus
API地址: https://dashscope.aliyuncs.com/compatible-mode/v1
API密钥: 在阿里云DashScope控制台获取
```
#### OpenAI GPT
```
模型: gpt-3.5-turbo 或 gpt-4
API地址: https://api.openai.com/v1
API密钥: 在OpenAI控制台获取
```
### 3. 议价策略配置
- **最大优惠百分比**: 建议设置5-15%
- **最大优惠金额**: 根据商品价值设置
- **最大议价轮数**: 建议3-5轮
## ⚙️ 详细配置
### 基本设置
| 配置项 | 说明 | 推荐值 |
|--------|------|--------|
| AI模型 | 选择使用的AI模型 | qwen-plus |
| API地址 | AI服务的API地址 | 默认值 |
| API密钥 | 访问AI服务的密钥 | 必填 |
### 议价设置
| 配置项 | 说明 | 推荐值 |
|--------|------|--------|
| 最大优惠百分比 | 最大可优惠的百分比 | 10% |
| 最大优惠金额 | 最大可优惠的金额 | 100元 |
| 最大议价轮数 | 最多允许议价的次数 | 3轮 |
### 提示词自定义
可以自定义四种类型的提示词:
```json
{
"classify": "意图分类提示词",
"price": "议价专家提示词",
"tech": "技术专家提示词",
"default": "通用客服提示词"
}
```
## 🔄 工作流程
### 1. 消息接收
系统接收到用户消息后首先检查该账号是否启用AI回复。
### 2. 意图识别
AI分析消息内容识别用户意图
- 价格相关 → 路由到价格专家
- 技术相关 → 路由到技术专家
- 其他咨询 → 路由到通用客服
### 3. 上下文构建
- 获取对话历史
- 加载商品信息
- 统计议价次数
### 4. 智能回复
根据意图类型和上下文信息,生成个性化回复。
### 5. 回复发送
在回复前添加 `[AI回复]` 标识,便于区分。
## 📊 优先级说明
当账号启用AI回复后系统回复优先级为
1. **🔥 API回复** (最高优先级)
2. **🤖 AI回复** (AI启用时)
3. **📝 关键词匹配** (AI禁用时)
4. **💬 默认回复** (最低优先级)
> ⚠️ **重要**: 启用AI回复后关键词匹配和默认回复将自动失效
## 🧪 功能测试
### 测试步骤
1. 在AI回复配置页面找到 **功能测试** 区域
2. 输入测试消息,如:"这个商品能便宜点吗?"
3. 设置商品价格
4. 点击 **测试AI回复** 按钮
5. 查看生成的回复效果
### 测试场景
- **议价测试**: "能便宜点吗?"、"最低多少钱?"
- **技术测试**: "这个怎么用?"、"有什么功能?"
- **通用测试**: "包邮吗?"、"什么时候发货?"
## 💡 最佳实践
### 1. API密钥管理
- 定期更换API密钥
- 监控API使用量和费用
- 设置合理的调用频率限制
### 2. 议价策略
- 根据商品类型调整议价幅度
- 高价值商品可设置更高的优惠金额
- 低价商品建议限制议价轮数
### 3. 提示词优化
- 根据实际业务场景自定义提示词
- 定期分析回复效果,优化提示词
- 保持回复风格的一致性
### 4. 监控和优化
- 定期查看AI回复的效果
- 分析用户反馈,调整配置
- 监控API调用成本
## ⚠️ 注意事项
### 安全性
- API密钥加密存储但请定期更换
- 建议使用子账号API密钥限制权限
- 监控异常调用,防止滥用
### 成本控制
- AI回复会产生API调用费用
- 建议设置合理的调用限制
- 监控每日/每月的使用量
### 合规性
- AI生成的内容可能需要人工审核
- 确保回复内容符合平台规则
- 避免过度承诺或误导用户
## 🔧 故障排除
### 常见问题
**Q: AI回复不生效**
A: 检查以下项目:
- 账号是否启用AI回复
- API密钥是否正确
- 网络连接是否正常
- API服务是否可用
**Q: 回复质量不佳?**
A: 尝试以下优化:
- 调整AI模型选择
- 自定义提示词
- 优化商品信息描述
- 增加测试和调优
**Q: API调用失败**
A: 检查以下方面:
- API密钥是否有效
- API地址是否正确
- 账户余额是否充足
- 请求频率是否超限
## 📞 技术支持
如果您在使用过程中遇到问题,可以:
1. 查看系统日志获取详细错误信息
2. 使用测试功能验证配置是否正确
3. 检查API服务商的状态页面
4. 联系技术支持获取帮助
---
🎉 **恭喜!** 您已经掌握了AI回复功能的使用方法。开始享受智能化的客服体验吧

146
CHANGELOG.md Normal file
View File

@ -0,0 +1,146 @@
# 📋 更新日志
本文档记录了闲鱼自动回复管理系统的所有重要更新和变更。
## [v2.0.0] - 2024-07-24
### 🎉 重大更新
- **AI智能回复系统**集成多种AI模型支持智能对话和议价
- **商品管理功能**:自动收集和管理商品信息
- **实时日志系统**:完整的日志收集、查看和分析功能
- **Docker容器化**完整的Docker部署支持
### ✨ 新增功能
- **多AI模型支持**支持通义千问、GPT等主流AI模型
- **智能意图识别**:自动识别价格咨询、技术问题、通用咨询
- **智能议价系统**:阶梯式降价策略,可设置最大优惠幅度
- **商品信息自动收集**:消息触发时自动提取并保存商品信息
- **批量商品获取**:一键获取账号下所有商品信息
- **实时日志查看**Web界面实时查看系统运行日志
- **日志过滤和搜索**:支持按级别、来源、关键词过滤日志
- **系统健康监控**:完整的系统健康检查和监控
- **数据备份恢复**:支持完整的数据备份和恢复功能
### 🔧 功能改进
- **用户界面优化**现代化的Web界面设计
- **性能优化**:异步处理,提高系统并发能力
- **安全增强**JWT认证数据加密存储
- **错误处理**:完善的错误处理和重试机制
- **配置管理**:灵活的配置文件管理系统
### 🐛 问题修复
- 修复WebSocket连接不稳定的问题
- 修复Cookie失效时的自动刷新机制
- 修复数据库并发访问的问题
- 修复文件上传的安全问题
- 修复日志文件过大的问题
### 📚 文档更新
- 完整的README.md文档
- 详细的功能使用说明
- Docker部署指南
- API接口文档
- 故障排除指南
## [v1.5.0] - 2024-06-15
### ✨ 新增功能
- **自动发货增强**支持API接口类型卡券
- **批量数据管理**:支持批量导入和管理卡券
- **发货规则优化**:更智能的商品匹配算法
- **消息通知格式化**:美化消息通知格式
### 🔧 功能改进
- 优化自动发货匹配逻辑
- 改进卡券管理界面
- 增强错误处理机制
- 提升系统稳定性
### 🐛 问题修复
- 修复发货规则匹配不准确的问题
- 修复批量数据消耗过快的问题
- 修复API接口调用失败的问题
## [v1.4.0] - 2024-05-20
### ✨ 新增功能
- **多账号管理**:支持同时管理多个闲鱼账号
- **关键词回复**:每个账号独立的关键词回复设置
- **用户认证系统**:安全的登录认证机制
- **数据持久化**SQLite数据库存储
### 🔧 功能改进
- 重构代码架构,提高可维护性
- 优化数据库设计
- 改进用户界面体验
- 增强系统安全性
## [v1.3.0] - 2024-04-25
### ✨ 新增功能
- **自动发货功能**:支持自动发送卡券和虚拟商品
- **发货规则配置**:灵活的发货规则设置
- **卡券管理**:支持多种卡券类型管理
### 🔧 功能改进
- 优化消息处理逻辑
- 改进WebSocket连接稳定性
- 增强日志记录功能
## [v1.2.0] - 2024-03-30
### ✨ 新增功能
- **Web管理界面**现代化的Web管理界面
- **实时状态监控**:实时查看系统运行状态
- **配置文件管理**:可视化配置文件编辑
### 🔧 功能改进
- 优化自动回复逻辑
- 改进错误处理机制
- 增强系统稳定性
## [v1.1.0] - 2024-02-28
### ✨ 新增功能
- **关键词匹配**:支持关键词自动回复
- **变量替换**:支持消息中的变量替换
- **日志系统**:完整的日志记录功能
### 🔧 功能改进
- 优化WebSocket连接处理
- 改进消息解析逻辑
- 增强系统容错能力
## [v1.0.0] - 2024-01-15
### 🎉 首次发布
- **基础自动回复**:支持闲鱼消息自动回复
- **WebSocket连接**稳定的WebSocket连接机制
- **Token管理**自动Token刷新和管理
- **消息处理**:完整的消息接收和处理流程
---
## 📝 版本说明
### 版本号规则
- **主版本号**:重大功能更新或架构变更
- **次版本号**:新功能添加或重要改进
- **修订版本号**:问题修复和小幅改进
### 更新类型说明
- 🎉 **重大更新**:重要的新功能或架构变更
- ✨ **新增功能**:新增的功能特性
- 🔧 **功能改进**:现有功能的优化和改进
- 🐛 **问题修复**Bug修复和问题解决
- 📚 **文档更新**:文档和说明的更新
- 🔒 **安全更新**:安全相关的更新和修复
### 兼容性说明
- **向后兼容**:新版本保持与旧版本的兼容性
- **配置迁移**:提供配置文件自动迁移功能
- **数据迁移**:提供数据库自动升级功能
---
**注意**:建议在升级前备份重要数据,详细的升级指南请参考相关文档。

220
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,220 @@
# 🤝 贡献指南
感谢您对闲鱼自动回复管理系统的关注!我们欢迎任何形式的贡献,包括但不限于代码、文档、问题反馈和功能建议。
## 📋 贡献方式
### 🐛 报告问题
如果您发现了bug或有改进建议
1. 检查 [Issues](https://github.com/your-repo/xianyu-auto-reply/issues) 确认问题未被报告
2. 创建新的Issue详细描述问题
3. 提供复现步骤和环境信息
4. 如果可能,提供错误日志和截图
### 💡 功能建议
如果您有新功能的想法:
1. 在Issues中创建功能请求
2. 详细描述功能需求和使用场景
3. 说明功能的预期效果
4. 讨论实现方案的可行性
### 🔧 代码贡献
我们欢迎代码贡献,请遵循以下流程:
#### 开发环境搭建
1. **Fork项目**到您的GitHub账号
2. **克隆项目**到本地:
```bash
git clone https://github.com/your-username/xianyu-auto-reply.git
cd xianyu-auto-reply
```
3. **创建虚拟环境**
```bash
python -m venv venv
source venv/bin/activate # Linux/Mac
# 或
venv\Scripts\activate # Windows
```
4. **安装依赖**
```bash
pip install -r requirements.txt
```
5. **运行测试**确保环境正常:
```bash
python Start.py
```
#### 开发流程
1. **创建分支**
```bash
git checkout -b feature/your-feature-name
```
2. **编写代码**,遵循项目的代码规范
3. **编写测试**,确保新功能有相应的测试用例
4. **运行测试**,确保所有测试通过
5. **提交代码**
```bash
git add .
git commit -m "feat: 添加新功能描述"
```
6. **推送分支**
```bash
git push origin feature/your-feature-name
```
7. **创建Pull Request**
## 📝 代码规范
### Python代码规范
- 遵循 [PEP 8](https://www.python.org/dev/peps/pep-0008/) 代码风格
- 使用有意义的变量和函数名
- 添加必要的注释和文档字符串
- 保持函数简洁,单一职责原则
### 提交信息规范
使用 [Conventional Commits](https://www.conventionalcommits.org/) 规范:
```
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
```
#### 提交类型
- `feat`: 新功能
- `fix`: 问题修复
- `docs`: 文档更新
- `style`: 代码格式调整
- `refactor`: 代码重构
- `test`: 测试相关
- `chore`: 构建过程或辅助工具的变动
#### 示例
```
feat(ai): 添加智能议价功能
- 实现阶梯式降价策略
- 支持最大优惠限制
- 添加议价轮数统计
Closes #123
```
### 文档规范
- 使用Markdown格式
- 保持文档结构清晰
- 添加必要的代码示例
- 及时更新相关文档
## 🧪 测试指南
### 运行测试
```bash
# 运行所有测试
python -m pytest
# 运行特定测试文件
python -m pytest tests/test_ai_reply.py
# 运行带覆盖率的测试
python -m pytest --cov=.
```
### 编写测试
- 为新功能编写单元测试
- 确保测试覆盖率不低于80%
- 使用有意义的测试名称
- 测试边界条件和异常情况
### 测试示例
```python
def test_ai_reply_with_valid_input():
"""测试AI回复功能的正常输入"""
# 准备测试数据
message = "这个商品能便宜点吗?"
# 执行测试
result = ai_reply_engine.process_message(message)
# 验证结果
assert result is not None
assert "优惠" in result
```
## 📚 文档贡献
### 文档类型
- **用户文档**:使用说明、配置指南
- **开发文档**API文档、架构说明
- **部署文档**:安装部署指南
### 文档更新
- 新功能需要更新相关文档
- 修复文档中的错误和过时信息
- 改进文档的可读性和准确性
## 🔍 代码审查
### 审查标准
- **功能正确性**:代码是否实现了预期功能
- **代码质量**:是否遵循代码规范
- **性能考虑**:是否有性能问题
- **安全性**:是否存在安全隐患
- **测试覆盖**:是否有足够的测试
### 审查流程
1. 提交Pull Request
2. 自动化测试运行
3. 代码审查和讨论
4. 修改和完善
5. 合并到主分支
## 🎯 贡献建议
### 适合新手的任务
- 修复文档中的错误
- 改进错误信息和提示
- 添加单元测试
- 优化用户界面
### 高级贡献
- 新功能开发
- 性能优化
- 架构改进
- 安全增强
## 📞 联系方式
### 获取帮助
- **GitHub Issues**:报告问题和讨论
- **GitHub Discussions**:一般性讨论和问答
- **Email**:紧急问题联系
### 社区参与
- 参与Issue讨论
- 帮助其他用户解决问题
- 分享使用经验和技巧
- 推广项目
## 🏆 贡献者认可
### 贡献者列表
我们会在项目中维护贡献者列表,感谢每一位贡献者的付出。
### 贡献统计
- 代码贡献
- 文档贡献
- 问题报告
- 功能建议
## 📄 许可证
通过贡献代码,您同意您的贡献将在 [MIT License](LICENSE) 下发布。
---
**再次感谢您的贡献!** 🙏
每一个贡献都让这个项目变得更好,无论大小,我们都非常感激。让我们一起构建一个更好的闲鱼自动回复管理系统!

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2025 肥极喵
Copyright (c) 2024 Xianyu Auto Reply System
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

551
README.md
View File

@ -1,173 +1,444 @@
# 🐟 XianYuAutoDeliveryX - 闲鱼虚拟商品商自动发货&聊天对接大模型
# 🚀 闲鱼自动回复管理系统
[![Python Version](https://img.shields.io/badge/python-3.7%2B-blue)](https://www.python.org/)
[![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
<div align="center">
**✨ 基于闲鱼API的自动发货系统支持虚拟商品商品聊天窗口自动发货、消息自动回复等功能。**
**⚠️ 注意:本项目仅供学习交流使用,请勿用于商业用途。**
![Python](https://img.shields.io/badge/Python-3.11+-blue.svg)
![FastAPI](https://img.shields.io/badge/FastAPI-0.111+-green.svg)
![Docker](https://img.shields.io/badge/Docker-支持-blue.svg)
![License](https://img.shields.io/badge/License-MIT-yellow.svg)
![Version](https://img.shields.io/badge/Version-v2.0.0-brightgreen.svg)
![Platform](https://img.shields.io/badge/Platform-Linux%20%7C%20Windows%20%7C%20macOS-lightgrey.svg)
## 🌟 核心特性
**一个功能强大的闲鱼自动回复管理系统支持多账号管理、AI智能回复、自动发货等功能**
- 🔐 **用户认证系统** - 安全的登录认证,保护管理界面
- 👥 **多账号管理** - 支持同时管理多个闲鱼账号
- 🎯 **智能关键词回复** - 每个账号独立的关键词回复设置
- 💾 **数据持久化** - SQLite数据库存储账号和关键词数据
- 🌐 **美观Web界面** - 响应式设计,操作简单直观
- 📡 **API接口** - 完整的RESTful API支持
- 🔄 **实时消息处理** - 基于WebSocket的实时消息监控
- 📊 **订单状态监控** - 实时跟踪订单状态变化
- 📝 **完善的日志系统** - 详细的操作日志记录
[功能特性](#-功能特性) • [快速开始](#-快速开始) • [部署方式](#-部署方式) • [使用文档](#-使用文档) • [API文档](#-api文档) • [贡献指南](#-贡献指南)
## 🛠️ 快速开始
</div>
### ⛳ 运行环境
- Python 3.7+
## 📋 项目概述
### 🎯 安装依赖
闲鱼自动回复管理系统是一个基于 Python + FastAPI 开发的自动化客服系统,专为闲鱼平台设计。系统通过 WebSocket 连接闲鱼服务器,实时接收和处理消息,提供智能化的自动回复服务。
### 🎯 核心优势
- **🤖 AI智能回复**集成多种AI模型支持意图识别和智能议价
- **🔄 多账号管理**:同时管理多个闲鱼账号,独立配置和监控
- **📦 商品管理**:自动收集和管理商品信息,支持批量操作
- **🚚 自动发货**:智能匹配发货规则,自动发送卡券信息
- **📊 实时监控**:完整的日志系统和状态监控
- **🐳 容器化部署**支持Docker一键部署简化运维
## ✨ 功能特性
### 🤖 AI智能回复
- **多模型支持**支持通义千问、GPT等主流AI模型
- **意图识别**:自动识别价格咨询、技术问题、通用咨询
- **智能议价**:阶梯式降价策略,可设置最大优惠幅度
- **上下文感知**:记住完整对话历史,提供连贯回复
- **自定义提示词**支持针对不同场景自定义AI提示词
### 👥 多账号管理
- **账号隔离**:每个账号独立配置和管理
- **批量操作**:支持批量添加、删除、配置账号
- **状态监控**:实时监控账号连接状态和消息处理情况
- **权限控制**基于JWT的安全认证系统
### 📦 商品管理
- **自动收集**:消息触发时自动收集商品信息
- **详情获取**通过API获取完整商品详情
- **批量管理**:支持查看、编辑、删除商品信息
- **智能匹配**:基于商品信息进行关键词匹配
### 🚚 自动发货
- **规则配置**:灵活的发货规则配置系统
- **卡券管理**:支持多种卡券类型和批量导入
- **智能匹配**:根据商品信息自动匹配发货规则
- **发货记录**:完整的发货历史记录和统计
### 📊 监控与日志
- **实时日志**:多级别日志记录和实时查看
- **性能监控**:系统资源使用情况监控
- **消息统计**:消息处理统计和分析
- **健康检查**:完整的系统健康检查机制
## 🛠️ 技术栈
### 后端技术
- **Python 3.11+**:主要开发语言
- **FastAPI**现代化的Web框架
- **SQLite**:轻量级数据库
- **WebSocket**:实时通信
- **AsyncIO**:异步编程
### 前端技术
- **HTML5 + CSS3**:现代化界面设计
- **JavaScript (ES6+)**:交互逻辑
- **Bootstrap**:响应式布局
- **Chart.js**:数据可视化
### 部署技术
- **Docker**:容器化部署
- **Docker Compose**:多容器编排
- **Nginx**:反向代理和负载均衡
- **SSL/TLS**:安全传输
## 🚀 快速开始
### 方式一Docker 部署(推荐)
1. **克隆项目**
```bash
git clone https://github.com/your-repo/xianyu-auto-reply.git
cd xianyu-auto-reply
```
2. **一键部署**
```bash
./deploy.sh
```
3. **访问系统**
- 打开浏览器访问http://localhost:8080
- 默认账号admin / admin123
### 方式二:本地部署
1. **安装依赖**
```bash
pip install -r requirements.txt
```
2. **启动系统**
```bash
python Start.py
```
3. **访问系统**
- 打开浏览器访问http://localhost:8080
## 📚 使用文档
### 基础使用
1. **[使用说明](./使用说明.md)** - 系统基础使用指南
2. **[Docker部署说明](./Docker部署说明.md)** - Docker部署详细说明
### 功能文档
1. **[AI回复功能指南](./AI_REPLY_GUIDE.md)** - AI回复功能详细说明
2. **[商品管理功能说明](./商品管理功能说明.md)** - 商品管理功能使用
3. **[自动发货功能说明](./自动发货功能说明.md)** - 自动发货配置和使用
4. **[日志管理功能说明](./日志管理功能说明.md)** - 日志查看和管理
5. **[获取所有商品功能说明](./获取所有商品功能说明.md)** - 商品批量获取功能
## 🔧 配置说明
### 环境变量配置
```bash
pip install -r requirements.txt
# 基础配置
TZ=Asia/Shanghai
WEB_PORT=8080
# 管理员账号
ADMIN_USERNAME=admin
ADMIN_PASSWORD=admin123
# AI回复配置
AI_REPLY_ENABLED=true
DEFAULT_AI_MODEL=qwen-plus
DEFAULT_AI_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
```
### 🎨 配置说明
1. 在 `global_config.yml` 中配置基本参数
2. 系统支持多账号管理可通过Web界面添加多个闲鱼账号Cookie
### 全局配置文件
主要配置文件为 `global_config.yml`,包含:
- API端点配置
- WebSocket连接配置
- 自动回复配置
- 日志配置
- 商品详情获取配置
### 🚀 运行项目
## 📡 API文档
### 认证接口
- `POST /login` - 用户登录
- `POST /logout` - 用户登出
### 账号管理
- `GET /cookies` - 获取所有账号
- `POST /cookies` - 添加新账号
- `DELETE /cookies/{cookie_id}` - 删除账号
### AI回复管理
- `GET /ai-reply/{cookie_id}` - 获取AI配置
- `POST /ai-reply/{cookie_id}` - 保存AI配置
- `POST /ai-reply/{cookie_id}/test` - 测试AI回复
### 商品管理
- `GET /items` - 获取所有商品
- `GET /items/cookie/{cookie_id}` - 获取指定账号商品
- `PUT /items/{cookie_id}/{item_id}` - 更新商品详情
### 系统监控
- `GET /health` - 健康检查
- `GET /logs` - 获取系统日志
- `GET /logs/stats` - 日志统计信息
完整API文档访问http://localhost:8080/docs
## 🏗️ 项目结构
```
xianyu-auto-reply/
├── Start.py # 项目启动入口
├── XianyuAutoAsync.py # 闲鱼WebSocket客户端
├── reply_server.py # FastAPI Web服务器
├── config.py # 配置管理
├── cookie_manager.py # Cookie账号管理
├── db_manager.py # 数据库管理
├── ai_reply_engine.py # AI回复引擎
├── file_log_collector.py # 文件日志收集器
├── bargain_demo.py # 议价功能演示
├── global_config.yml # 全局配置文件
├── requirements.txt # Python依赖
├── Dockerfile # Docker镜像构建
├── docker-compose.yml # Docker编排配置
├── deploy.sh # 部署脚本
├── static/ # 前端静态文件
│ ├── index.html # 主页面
│ ├── login.html # 登录页面
│ └── xianyu_js_version_2.js # 前端逻辑
├── utils/ # 工具模块
│ ├── xianyu_utils.py # 闲鱼工具函数
│ ├── message_utils.py # 消息处理工具
│ └── ws_utils.py # WebSocket工具
├── nginx/ # Nginx配置
├── docs/ # 文档目录
└── backups/ # 备份目录
```
## 🤝 贡献指南
我们欢迎任何形式的贡献!请查看 [CONTRIBUTING.md](CONTRIBUTING.md) 了解详细的贡献指南。
### 快速开始贡献
1. **Fork** 项目到你的GitHub账号
2. **克隆**项目到本地开发环境
3. **创建分支**进行功能开发或问题修复
4. **提交代码**并创建Pull Request
### 贡献类型
- 🐛 **问题报告**发现bug或提出改进建议
- 💡 **功能建议**:提出新功能想法
- 🔧 **代码贡献**:修复问题或开发新功能
- 📚 **文档改进**:完善文档和说明
- 🧪 **测试用例**:添加或改进测试
详细信息请参考:[贡献指南](CONTRIBUTING.md)
## 📄 许可证
本项目采用 MIT 许可证,详情请查看 [LICENSE](LICENSE) 文件。
## 📋 更新日志
查看 [CHANGELOG.md](CHANGELOG.md) 了解详细的版本更新历史。
## 🙏 致谢
感谢所有为这个项目做出贡献的开发者和用户!
### 特别感谢
- 所有提交代码的贡献者
- 提供问题反馈的用户
- 完善文档的志愿者
- 推广项目的支持者
### 技术支持
- [FastAPI](https://fastapi.tiangolo.com/) - 现代化的Web框架
- [SQLite](https://www.sqlite.org/) - 轻量级数据库
- [Docker](https://www.docker.com/) - 容器化技术
- [Loguru](https://github.com/Delgan/loguru) - 优秀的日志库
---
<div align="center">
**如果这个项目对你有帮助,请给个 ⭐ Star 支持一下!**
[📋 报告问题](https://github.com/your-repo/xianyu-auto-reply/issues) • [💡 功能建议](https://github.com/your-repo/xianyu-auto-reply/issues) • [🤝 参与贡献](https://github.com/your-repo/xianyu-auto-reply/pulls) • [📖 查看文档](https://github.com/your-repo/xianyu-auto-reply/wiki)
**让我们一起构建更好的闲鱼自动化工具!** 🚀
</div>
## 🔧 核心模块说明
### Start.py - 项目启动入口
- 初始化文件日志收集器
- 创建和管理 CookieManager
- 启动 FastAPI Web服务器
- 加载配置文件和环境变量中的账号
### XianyuAutoAsync.py - 闲鱼WebSocket客户端
- 维持与闲鱼服务器的WebSocket连接
- 处理消息接收和发送
- 自动刷新token和维持心跳
- 商品信息获取和处理
- 自动回复逻辑处理
### reply_server.py - FastAPI Web服务器
- 提供Web管理界面
- RESTful API接口
- 用户认证和权限控制
- 文件上传和下载
- 健康检查和监控
### ai_reply_engine.py - AI回复引擎
- 多AI模型支持通义千问、GPT等
- 意图识别和分类
- 智能议价逻辑
- 对话历史管理
- 自定义提示词处理
### db_manager.py - 数据库管理
- SQLite数据库操作
- 数据表结构管理
- 数据备份和恢复
- 事务处理和连接池
## 🎮 使用场景
### 个人卖家
- **自动客服**24小时自动回复买家咨询
- **智能议价**:自动处理价格谈判,提高成交率
- **快速发货**:自动发送卡券和虚拟商品
### 商家店铺
- **多账号管理**:统一管理多个闲鱼账号
- **批量操作**:批量设置关键词和回复规则
- **数据分析**:查看消息统计和销售数据
### 代运营服务
- **客户隔离**:为不同客户提供独立的账号管理
- **定制化配置**:根据客户需求定制回复策略
- **监控报告**:提供详细的运营数据报告
## 🔒 安全特性
### 数据安全
- **本地存储**:所有数据存储在本地,不上传到第三方
- **加密传输**支持HTTPS和WSS加密传输
- **权限控制**基于JWT的用户认证系统
### 隐私保护
- **Cookie加密**:敏感信息加密存储
- **日志脱敏**:自动过滤敏感信息
- **访问控制**IP白名单和访问频率限制
## 📈 性能优化
### 系统性能
- **异步处理**:全异步架构,高并发处理能力
- **连接池**:数据库连接池,提高数据库操作效率
- **缓存机制**:智能缓存,减少重复请求
### 资源优化
- **内存管理**:自动清理过期数据和缓存
- **日志轮转**:自动清理过期日志文件
- **资源限制**Docker资源限制防止资源滥用
## 🚨 故障排除
### 常见问题
**Q: 系统启动失败?**
A: 检查以下项目:
- Python版本是否为3.11+
- 依赖包是否正确安装
- 端口8080是否被占用
- 配置文件是否存在
**Q: WebSocket连接失败**
A: 检查以下方面:
- 网络连接是否正常
- Cookie是否有效
- 防火墙设置
- 代理配置
**Q: AI回复不工作**
A: 检查以下配置:
- AI API密钥是否正确
- API地址是否可访问
- 账户余额是否充足
- 网络连接是否稳定
### 日志查看
```bash
python Start.py
# 查看实时日志
docker-compose logs -f
# 查看特定服务日志
docker-compose logs xianyu-app
# 查看系统日志文件
tail -f logs/xianyu_$(date +%Y-%m-%d).log
```
### 🔐 登录系统
1. 启动后访问 `http://localhost:8080`
2. 默认登录账号:
- 用户名:`admin`
- 密码:`admin123`
3. 登录后可进入管理界面进行操作
## 🤝 贡献指南
## 📁 项目结构
```
├── Start.py # 项目启动入口
├── XianyuAutoAsync.py # 核心业务逻辑
├── config.py # 配置管理
├── cookie_manager.py # Cookie管理器
├── db_manager.py # 数据库管理
├── reply_server.py # FastAPI服务器
├── utils/ # 工具函数目录
│ ├── xianyu_utils.py # 闲鱼相关工具
│ ├── message_utils.py # 消息处理工具
│ └── ws_utils.py # WebSocket工具
├── static/ # 静态资源
│ ├── index.html # 管理界面
│ └── login.html # 登录页面
├── logs/ # 日志文件
├── global_config.yml # 全局配置文件
├── xianyu_data.db # SQLite数据库
└── requirements.txt # Python依赖
```
我们欢迎任何形式的贡献!请查看 [CONTRIBUTING.md](CONTRIBUTING.md) 了解详细的贡献指南。
## 🎯 主要功能
### 快速开始贡献
1. **Fork** 项目到你的GitHub账号
2. **克隆**项目到本地开发环境
3. **创建分支**进行功能开发或问题修复
4. **提交代码**并创建Pull Request
### 1. 用户认证系统
- 安全的登录认证机制
- Session token管理
- 自动登录状态检查
- 登出功能
### 贡献类型
- 🐛 **问题报告**发现bug或提出改进建议
- 💡 **功能建议**:提出新功能想法
- 🔧 **代码贡献**:修复问题或开发新功能
- 📚 **文档改进**:完善文档和说明
- 🧪 **测试用例**:添加或改进测试
### 2. 多账号管理
- 支持添加多个闲鱼账号
- 每个账号独立管理
- Cookie安全存储
- 账号状态监控
### 开发规范
- 遵循 [PEP 8](https://www.python.org/dev/peps/pep-0008/) 代码风格
- 使用 [Conventional Commits](https://www.conventionalcommits.org/) 提交规范
- 为新功能添加相应的测试用例
- 更新相关文档和说明
### 3. 智能关键词回复
- 每个账号独立的关键词设置
- 支持变量替换:`{send_user_name}`, `{send_user_id}`, `{send_message}`
- 实时关键词匹配
- 默认回复机制
详细信息请参考:[贡献指南](CONTRIBUTING.md)
### 4. Web管理界面
- 响应式设计,支持移动端
- 直观的操作界面
- 实时数据更新
- 操作反馈提示
## 📄 许可证
## 🔌 API 接口说明
本项目采用 MIT 许可证,详情请查看 [LICENSE](LICENSE) 文件。
### 智能回复接口
`POST http://localhost:8080/xianyu/reply`
## <20> 更新日志
#### 接口说明
你需要实现这个接口,本项目会调用这个接口获取自动回复的内容并发送给客户
不实现这个接口也没关系,系统会默认回复,你也可以配置默认回复的内容
用于处理闲鱼消息的自动回复,支持对接大语言模型进行智能回复。
查看 [CHANGELOG.md](CHANGELOG.md) 了解详细的版本更新历史。
**通过这个接口可以检测到用户是否已付款,然后回复虚拟资料内容即可**
#### 请求参数
```json
{
"msg_time": "消息时间",
"user_url": "用户主页URL",
"send_user_id": "发送者ID",
"send_user_name": "发送者昵称",
"item_id": "商品ID",
"send_message": "发送的消息内容",
"chat_id": "会话ID"
}
```
## <20>🙏 致谢
#### 响应格式
```json
{
"code": 200,
"data": {
"send_msg": "回复的消息内容"
}
}
```
感谢所有为这个项目做出贡献的开发者和用户!
#### 配置示例
```yaml
AUTO_REPLY:
api:
enabled: true # 是否启用API回复
timeout: 10 # 超时时间(秒)
url: http://localhost:8080/xianyu/reply
```
### 特别感谢
- 所有提交代码的贡献者
- 提供问题反馈的用户
- 完善文档的志愿者
- 推广项目的支持者
#### 使用场景
- 当收到买家消息时,系统会自动调用此接口
- 支持接入 ChatGPT、文心一言等大语言模型
- 支持自定义回复规则和模板
- 支持消息变量替换(如 `{send_user_name}`
### 技术支持
- [FastAPI](https://fastapi.tiangolo.com/) - 现代化的Web框架
- [SQLite](https://www.sqlite.org/) - 轻量级数据库
- [Docker](https://www.docker.com/) - 容器化技术
- [Loguru](https://github.com/Delgan/loguru) - 优秀的日志库
#### 注意事项
- 接口需要返回正确的状态码200和消息内容
- 建议实现错误重试机制
- 注意处理超时情况默认10秒
- 可以根据需要扩展更多的参数和功能
---
## 🗝️ 注意事项
- 请确保闲鱼账号已登录并获取有效的 Cookie
- 建议在正式环境使用前先在测试环境验证
- 定期检查日志文件,及时处理异常情况
- 使用大模型时注意 API 调用频率和成本控制
<div align="center">
## 📝 效果
**如果这个项目对你有帮助,请给个 ⭐ Star 支持一下!**
[📋 报告问题](https://github.com/your-repo/xianyu-auto-reply/issues) • [💡 功能建议](https://github.com/your-repo/xianyu-auto-reply/issues) • [🤝 参与贡献](https://github.com/your-repo/xianyu-auto-reply/pulls) • [📖 查看文档](https://github.com/your-repo/xianyu-auto-reply/wiki)
![image-20250611004531745](https://typeropic.oss-cn-beijing.aliyuncs.com/cp/image-20250611004531745.png)
**让我们一起构建更好的闲鱼自动化工具!** 🚀
![image-20250611004549662](https://typeropic.oss-cn-beijing.aliyuncs.com/cp/image-20250611004549662.png)
## 🧸特别鸣谢
本项目参考了以下开源项目: https://github.com/cv-cat/XianYuApis
感谢[@CVcat](https://github.com/cv-cat)的技术支持
## 📞 联系方式
如有问题或建议,欢迎提交 Issue 或 Pull Request。
## 技术交流
![image-20250611004141387](https://typeropic.oss-cn-beijing.aliyuncs.com/cp/image-20250611004141387.png)
</div>

View File

@ -1,92 +0,0 @@
# 🎨 界面优化总结
## ✨ 主要改进
### 1. 🎯 Cookie显示优化
- **❌ 修改前**: Cookie值被隐藏为星号 (`****`)
- **✅ 修改后**: 显示完整的Cookie内容便于查看和调试
### 2. 🎨 视觉设计升级
- **现代化配色方案**: 使用更现代的紫色主题 (`#4f46e5`)
- **渐变背景**: 美丽的渐变背景和卡片效果
- **毛玻璃效果**: 卡片使用 `backdrop-filter: blur()` 实现毛玻璃效果
- **阴影和动画**: 悬停时的阴影和位移动画效果
### 3. 🔧 功能增强
- **一键复制Cookie**: 点击Cookie值或复制按钮即可复制到剪贴板
- **改进的按钮组**: 更紧凑的按钮布局,包含复制功能
- **更好的空状态**: 当没有账号时显示更友好的提示
### 4. 📱 响应式设计
- **移动端优化**: 在小屏幕上按钮垂直排列
- **自适应布局**: 表格和卡片在不同屏幕尺寸下的自适应
## 🛠️ 技术改进
### 新增API接口
```javascript
GET /cookies/details
```
返回包含Cookie ID和完整值的详细信息而不仅仅是ID列表。
### CSS样式优化
- **CSS变量**: 统一的颜色管理
- **现代字体**: 使用 Inter 字体提升可读性
- **代码字体**: Cookie值使用等宽字体 (JetBrains Mono)
- **流畅动画**: 所有交互都有平滑的过渡效果
### JavaScript功能增强
- **复制功能**: 支持现代浏览器的 Clipboard API
- **降级方案**: 对于不支持的浏览器提供传统复制方法
- **用户反馈**: 复制成功/失败的Toast提示
## 🎯 用户体验提升
### 1. Cookie管理
- **完整显示**: 不再隐藏Cookie内容便于调试
- **一键复制**: 快速复制Cookie值到剪贴板
- **格式化显示**: 使用等宽字体和适当的行高
### 2. 视觉反馈
- **悬停效果**: 所有可交互元素都有悬停反馈
- **状态指示**: 清晰的按钮状态和颜色区分
- **加载动画**: 优雅的加载状态显示
### 3. 操作便利性
- **按钮分组**: 相关操作按钮紧凑排列
- **图标提示**: 每个按钮都有清晰的图标和提示
- **确认对话框**: 危险操作有确认提示
## 📊 界面对比
| 功能 | 修改前 | 修改后 |
|------|--------|--------|
| Cookie显示 | 隐藏为星号 | 完整显示 |
| 复制功能 | 无 | 一键复制 |
| 视觉效果 | 基础Bootstrap | 现代化渐变设计 |
| 响应式 | 基本支持 | 完全优化 |
| 用户反馈 | 基础提示 | 丰富的Toast反馈 |
## 🚀 使用说明
### 访问界面
1. 启动系统: `python Start.py`
2. 打开浏览器: `http://localhost:8080`
3. 登录: `admin` / `admin123`
### 主要功能
- **添加账号**: 在顶部表单中输入账号ID和Cookie值
- **查看Cookie**: 完整的Cookie值显示在表格中
- **复制Cookie**: 点击Cookie值或复制按钮
- **管理关键词**: 点击关键词按钮设置自动回复
- **删除账号**: 点击删除按钮(有确认提示)
## 🎉 总结
这次界面优化大幅提升了用户体验:
- ✅ **Cookie不再隐藏**,便于查看和调试
- ✅ **现代化设计**,视觉效果更佳
- ✅ **功能增强**,操作更便利
- ✅ **响应式优化**,支持各种设备
界面现在更加美观、实用和用户友好!🎨✨

View File

@ -650,7 +650,7 @@ class XianyuLive:
if result:
return result
logger.warning("所有方法都未能提取到商品ID")
logger.debug("所有方法都未能提取到商品ID")
return None
except Exception as e:
@ -713,6 +713,105 @@ class XianyuLive:
logger.error(f"获取默认回复失败: {self._safe_str(e)}")
return None
async def get_keyword_reply(self, send_user_name: str, send_user_id: str, send_message: str) -> str:
"""获取关键词匹配回复"""
try:
from db_manager import db_manager
# 获取当前账号的关键词列表
keywords = db_manager.get_keywords(self.cookie_id)
if not keywords:
logger.debug(f"账号 {self.cookie_id} 没有配置关键词")
return None
# 遍历关键词,查找匹配
for keyword, reply in keywords:
if keyword.lower() in send_message.lower():
# 进行变量替换
try:
formatted_reply = reply.format(
send_user_name=send_user_name,
send_user_id=send_user_id,
send_message=send_message
)
logger.info(f"关键词匹配成功: '{keyword}' -> {formatted_reply}")
return f"[关键词回复] {formatted_reply}"
except Exception as format_error:
logger.error(f"关键词回复变量替换失败: {self._safe_str(format_error)}")
# 如果变量替换失败,返回原始内容
return f"[关键词回复] {reply}"
logger.debug(f"未找到匹配的关键词: {send_message}")
return None
except Exception as e:
logger.error(f"获取关键词回复失败: {self._safe_str(e)}")
return None
async def get_ai_reply(self, send_user_name: str, send_user_id: str, send_message: str, item_id: str, chat_id: str):
"""获取AI回复"""
try:
from ai_reply_engine import ai_reply_engine
# 检查是否启用AI回复
if not ai_reply_engine.is_ai_enabled(self.cookie_id):
logger.debug(f"账号 {self.cookie_id} 未启用AI回复")
return None
# 从数据库获取商品信息
from db_manager import db_manager
item_info_raw = db_manager.get_item_info(self.cookie_id, item_id)
if not item_info_raw:
logger.debug(f"数据库中无商品信息: {item_id}")
# 使用默认商品信息
item_info = {
'title': '商品信息获取失败',
'price': 0,
'desc': '暂无商品描述'
}
else:
# 解析数据库中的商品信息
item_info = {
'title': item_info_raw.get('item_title', '未知商品'),
'price': self._parse_price(item_info_raw.get('item_price', '0')),
'desc': item_info_raw.get('item_description', '暂无商品描述')
}
# 生成AI回复
reply = ai_reply_engine.generate_reply(
message=send_message,
item_info=item_info,
chat_id=chat_id,
cookie_id=self.cookie_id,
user_id=send_user_id,
item_id=item_id
)
if reply:
logger.info(f"AI回复生成成功: {reply}")
return f"[AI回复] {reply}"
else:
logger.debug(f"AI回复生成失败")
return None
except Exception as e:
logger.error(f"获取AI回复失败: {self._safe_str(e)}")
return None
def _parse_price(self, price_str: str) -> float:
"""解析价格字符串为数字"""
try:
if not price_str:
return 0.0
# 移除非数字字符,保留小数点
import re
price_clean = re.sub(r'[^\d.]', '', str(price_str))
return float(price_clean) if price_clean else 0.0
except:
return 0.0
async def send_notification(self, send_user_name: str, send_user_id: str, send_message: str, item_id: str = None):
"""发送消息通知"""
try:
@ -911,11 +1010,11 @@ class XianyuLive:
logger.warning(f"数据库中商品标题和详情都为空且无法从API获取: {item_id}")
search_text = item_title or item_id
else:
logger.warning(f"数据库中未找到商品信息: {item_id}")
logger.debug(f"数据库中未找到商品信息: {item_id}")
search_text = item_title or item_id
except Exception as db_e:
logger.warning(f"从数据库获取商品信息失败: {self._safe_str(db_e)}")
logger.debug(f"从数据库获取商品信息失败: {self._safe_str(db_e)}")
search_text = item_title or item_id
if not search_text:
@ -1499,7 +1598,7 @@ class XianyuLive:
else:
user_id = "unknown_user"
except Exception as e:
logger.warning(f"提取用户ID失败: {self._safe_str(e)}")
logger.debug(f"提取用户ID失败: {self._safe_str(e)}")
user_id = "unknown_user"
# 安全地获取商品ID
@ -1542,7 +1641,7 @@ class XianyuLive:
if not item_id:
item_id = f"auto_{user_id}_{int(time.time())}"
logger.warning(f"无法提取商品ID使用默认值: {item_id}")
logger.debug(f"无法提取商品ID使用默认值: {item_id}")
except Exception as e:
logger.error(f"提取商品ID时发生错误: {self._safe_str(e)}")
@ -1719,10 +1818,20 @@ class XianyuLive:
# 记录回复来源
reply_source = 'API' # 默认假设是API回复
# 如果API回复失败或未启用API尝试使用默认回复
# 如果API回复失败或未启用API尝试使用AI回复
if not reply:
reply = await self.get_default_reply(send_user_name, send_user_id, send_message)
reply_source = '默认' # 标记为默认回复
reply = await self.get_ai_reply(send_user_name, send_user_id, send_message, item_id, chat_id)
if reply:
reply_source = 'AI' # 标记为AI回复
else:
# 如果AI回复也失败尝试关键词匹配
reply = await self.get_keyword_reply(send_user_name, send_user_id, send_message)
if reply:
reply_source = '关键词' # 标记为关键词回复
else:
# 最后尝试使用默认回复
reply = await self.get_default_reply(send_user_name, send_user_id, send_message)
reply_source = '默认' # 标记为默认回复
# 保存商品信息到数据库记录通知时传递的item_id
if item_id:

273
ai_reply_engine.py Normal file
View File

@ -0,0 +1,273 @@
"""
AI回复引擎模块
集成XianyuAutoAgent的AI回复功能到现有项目中
"""
import os
import json
import time
import sqlite3
from typing import List, Dict, Optional
from loguru import logger
from openai import OpenAI
from db_manager import db_manager
class AIReplyEngine:
"""AI回复引擎"""
def __init__(self):
self.clients = {} # 存储不同账号的OpenAI客户端
self.agents = {} # 存储不同账号的Agent实例
self._init_default_prompts()
def _init_default_prompts(self):
"""初始化默认提示词"""
self.default_prompts = {
'classify': '''你是一个意图分类专家,需要判断用户消息的意图类型。
请根据用户消息内容返回以下意图之一
- price: 价格相关议价优惠降价等
- tech: 技术相关产品参数使用方法故障等
- default: 其他一般咨询
只返回意图类型不要其他内容''',
'price': '''你是一位经验丰富的销售专家,擅长议价。
语言要求简短直接每句10总字数40
议价策略
1. 根据议价次数递减优惠第1次小幅优惠第2次中等优惠第3次最大优惠
2. 接近最大议价轮数时要坚持底线强调商品价值
3. 优惠不能超过设定的最大百分比和金额
4. 语气要友好但坚定突出商品优势
注意结合商品信息对话历史和议价设置给出合适的回复''',
'tech': '''你是一位技术专家,专业解答产品相关问题。
语言要求简短专业每句10总字数40
回答重点产品功能使用方法注意事项
注意基于商品信息回答避免过度承诺''',
'default': '''你是一位资深电商卖家,提供优质客服。
语言要求简短友好每句10总字数40
回答重点商品介绍物流售后等常见问题
注意结合商品信息给出实用建议'''
}
def get_client(self, cookie_id: str) -> Optional[OpenAI]:
"""获取指定账号的OpenAI客户端"""
if cookie_id not in self.clients:
settings = db_manager.get_ai_reply_settings(cookie_id)
if not settings['ai_enabled'] or not settings['api_key']:
return None
try:
self.clients[cookie_id] = OpenAI(
api_key=settings['api_key'],
base_url=settings['base_url']
)
logger.info(f"为账号 {cookie_id} 创建OpenAI客户端")
except Exception as e:
logger.error(f"创建OpenAI客户端失败 {cookie_id}: {e}")
return None
return self.clients[cookie_id]
def is_ai_enabled(self, cookie_id: str) -> bool:
"""检查指定账号是否启用AI回复"""
settings = db_manager.get_ai_reply_settings(cookie_id)
return settings['ai_enabled']
def detect_intent(self, message: str, cookie_id: str) -> str:
"""检测用户消息意图"""
client = self.get_client(cookie_id)
if not client:
return 'default'
try:
settings = db_manager.get_ai_reply_settings(cookie_id)
custom_prompts = json.loads(settings['custom_prompts']) if settings['custom_prompts'] else {}
classify_prompt = custom_prompts.get('classify', self.default_prompts['classify'])
response = client.chat.completions.create(
model=settings['model_name'],
messages=[
{"role": "system", "content": classify_prompt},
{"role": "user", "content": message}
],
max_tokens=10,
temperature=0.1
)
intent = response.choices[0].message.content.strip().lower()
if intent in ['price', 'tech', 'default']:
return intent
else:
return 'default'
except Exception as e:
logger.error(f"意图检测失败 {cookie_id}: {e}")
return 'default'
def generate_reply(self, message: str, item_info: dict, chat_id: str,
cookie_id: str, user_id: str, item_id: str) -> Optional[str]:
"""生成AI回复"""
if not self.is_ai_enabled(cookie_id):
return None
client = self.get_client(cookie_id)
if not client:
return None
try:
# 1. 获取AI回复设置
settings = db_manager.get_ai_reply_settings(cookie_id)
# 2. 检测意图
intent = self.detect_intent(message, cookie_id)
logger.info(f"检测到意图: {intent} (账号: {cookie_id})")
# 3. 获取对话历史
context = self.get_conversation_context(chat_id, cookie_id)
# 4. 获取议价次数
bargain_count = self.get_bargain_count(chat_id, cookie_id)
# 5. 检查议价轮数限制
if intent == "price":
max_bargain_rounds = settings.get('max_bargain_rounds', 3)
if bargain_count >= max_bargain_rounds:
logger.info(f"议价次数已达上限 ({bargain_count}/{max_bargain_rounds}),拒绝继续议价")
# 返回拒绝议价的回复
refuse_reply = f"抱歉,这个价格已经是最优惠的了,不能再便宜了哦!"
# 保存对话记录
self.save_conversation(chat_id, cookie_id, user_id, item_id, "user", message, intent)
self.save_conversation(chat_id, cookie_id, user_id, item_id, "assistant", refuse_reply, intent)
return refuse_reply
# 6. 构建提示词
custom_prompts = json.loads(settings['custom_prompts']) if settings['custom_prompts'] else {}
system_prompt = custom_prompts.get(intent, self.default_prompts[intent])
# 7. 构建商品信息
item_desc = f"商品标题: {item_info.get('title', '未知')}\n"
item_desc += f"商品价格: {item_info.get('price', '未知')}\n"
item_desc += f"商品描述: {item_info.get('desc', '')}"
# 8. 构建对话历史
context_str = "\n".join([f"{msg['role']}: {msg['content']}" for msg in context[-10:]]) # 最近10条
# 9. 构建用户消息
max_bargain_rounds = settings.get('max_bargain_rounds', 3)
max_discount_percent = settings.get('max_discount_percent', 10)
max_discount_amount = settings.get('max_discount_amount', 100)
user_prompt = f"""商品信息:
{item_desc}
对话历史
{context_str}
议价设置
- 当前议价次数{bargain_count}
- 最大议价轮数{max_bargain_rounds}
- 最大优惠百分比{max_discount_percent}%
- 最大优惠金额{max_discount_amount}
用户消息{message}
请根据以上信息生成回复"""
# 10. 调用AI生成回复
response = client.chat.completions.create(
model=settings['model_name'],
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt}
],
max_tokens=100,
temperature=0.7
)
reply = response.choices[0].message.content.strip()
# 11. 保存对话记录
self.save_conversation(chat_id, cookie_id, user_id, item_id, "user", message, intent)
self.save_conversation(chat_id, cookie_id, user_id, item_id, "assistant", reply, intent)
# 12. 更新议价次数
if intent == "price":
self.increment_bargain_count(chat_id, cookie_id)
logger.info(f"AI回复生成成功 (账号: {cookie_id}): {reply}")
return reply
except Exception as e:
logger.error(f"AI回复生成失败 {cookie_id}: {e}")
return None
def get_conversation_context(self, chat_id: str, cookie_id: str, limit: int = 20) -> List[Dict]:
"""获取对话上下文"""
try:
with db_manager.lock:
cursor = db_manager.conn.cursor()
cursor.execute('''
SELECT role, content FROM ai_conversations
WHERE chat_id = ? AND cookie_id = ?
ORDER BY created_at DESC LIMIT ?
''', (chat_id, cookie_id, limit))
results = cursor.fetchall()
# 反转顺序,使其按时间正序
context = [{"role": row[0], "content": row[1]} for row in reversed(results)]
return context
except Exception as e:
logger.error(f"获取对话上下文失败: {e}")
return []
def save_conversation(self, chat_id: str, cookie_id: str, user_id: str,
item_id: str, role: str, content: str, intent: str = None):
"""保存对话记录"""
try:
with db_manager.lock:
cursor = db_manager.conn.cursor()
cursor.execute('''
INSERT INTO ai_conversations
(cookie_id, chat_id, user_id, item_id, role, content, intent)
VALUES (?, ?, ?, ?, ?, ?, ?)
''', (cookie_id, chat_id, user_id, item_id, role, content, intent))
db_manager.conn.commit()
except Exception as e:
logger.error(f"保存对话记录失败: {e}")
def get_bargain_count(self, chat_id: str, cookie_id: str) -> int:
"""获取议价次数"""
try:
with db_manager.lock:
cursor = db_manager.conn.cursor()
cursor.execute('''
SELECT COUNT(*) FROM ai_conversations
WHERE chat_id = ? AND cookie_id = ? AND intent = 'price' AND role = 'user'
''', (chat_id, cookie_id))
result = cursor.fetchone()
return result[0] if result else 0
except Exception as e:
logger.error(f"获取议价次数失败: {e}")
return 0
def increment_bargain_count(self, chat_id: str, cookie_id: str):
"""增加议价次数(通过保存记录自动增加)"""
# 议价次数通过查询price意图的用户消息数量来计算无需单独操作
pass
def clear_client_cache(self, cookie_id: str = None):
"""清理客户端缓存"""
if cookie_id:
self.clients.pop(cookie_id, None)
logger.info(f"清理账号 {cookie_id} 的客户端缓存")
else:
self.clients.clear()
logger.info("清理所有客户端缓存")
# 全局AI回复引擎实例
ai_reply_engine = AIReplyEngine()

180
bargain_demo.py Normal file
View File

@ -0,0 +1,180 @@
#!/usr/bin/env python3
"""
议价功能演示脚本
展示AI回复的议价轮数限制功能
"""
import asyncio
import sys
import os
# 添加项目根目录到Python路径
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from ai_reply_engine import ai_reply_engine
from db_manager import db_manager
def simulate_bargain_conversation():
"""模拟议价对话流程"""
print("🎭 模拟议价对话流程")
print("=" * 50)
# 测试参数
cookie_id = "demo_account_001"
chat_id = "demo_chat_001"
user_id = "customer_001"
item_id = "item_12345"
user_name = "小明"
# 商品信息
item_info = {
'title': 'iPhone 14 Pro 256GB 深空黑色',
'price': 8999,
'desc': '全新未拆封,国行正品,支持全国联保'
}
# 设置AI回复配置模拟
ai_settings = {
'ai_enabled': True,
'model_name': 'qwen-plus',
'api_key': 'demo-key',
'base_url': 'https://dashscope.aliyuncs.com/compatible-mode/v1',
'max_discount_percent': 10, # 最大优惠10%
'max_discount_amount': 500, # 最大优惠500元
'max_bargain_rounds': 3, # 最大议价3轮
'custom_prompts': ''
}
# 保存配置
db_manager.save_ai_reply_settings(cookie_id, ai_settings)
# 清理之前的对话
try:
with db_manager.lock:
cursor = db_manager.conn.cursor()
cursor.execute('DELETE FROM ai_conversations WHERE cookie_id = ? AND chat_id = ?',
(cookie_id, chat_id))
db_manager.conn.commit()
except:
pass
print(f"📱 商品信息:")
print(f" 标题: {item_info['title']}")
print(f" 价格: ¥{item_info['price']}")
print(f" 描述: {item_info['desc']}")
print(f"\n⚙️ 议价设置:")
print(f" 最大议价轮数: {ai_settings['max_bargain_rounds']}")
print(f" 最大优惠百分比: {ai_settings['max_discount_percent']}%")
print(f" 最大优惠金额: ¥{ai_settings['max_discount_amount']}")
# 模拟议价对话
bargain_messages = [
"你好这个iPhone能便宜点吗",
"8500能卖吗",
"8800行不行最后一次了",
"8700真的不能再少了"
]
print(f"\n💬 议价对话模拟:")
print("-" * 30)
for i, message in enumerate(bargain_messages, 1):
print(f"\n{i}轮议价:")
print(f"👤 {user_name}: {message}")
# 检查当前议价次数
current_count = ai_reply_engine.get_bargain_count(chat_id, cookie_id)
max_rounds = ai_settings['max_bargain_rounds']
print(f"📊 当前议价次数: {current_count}/{max_rounds}")
# 模拟意图检测为price
intent = "price"
# 检查是否超出限制
if current_count >= max_rounds:
print(f"🚫 已达到最大议价轮数限制!")
refuse_reply = "抱歉,这个价格已经是最优惠的了,不能再便宜了哦!"
print(f"🤖 AI回复: {refuse_reply}")
# 保存对话记录
ai_reply_engine.save_conversation(chat_id, cookie_id, user_id, item_id, "user", message, intent)
ai_reply_engine.save_conversation(chat_id, cookie_id, user_id, item_id, "assistant", refuse_reply, intent)
print(f"✋ 议价结束,系统拒绝继续议价")
break
else:
# 模拟AI回复因为没有真实API密钥这里手动模拟
if i == 1:
ai_reply = "您好这个价格已经很优惠了最多可以优惠200元8799元怎么样"
elif i == 2:
ai_reply = "8500太低了我们再让一点8699元这已经是很大的优惠了"
elif i == 3:
ai_reply = "好的看您很有诚意8799元成交这真的是最低价了"
else:
ai_reply = "抱歉,这个价格已经是最优惠的了!"
print(f"🤖 AI回复: {ai_reply}")
# 保存对话记录
ai_reply_engine.save_conversation(chat_id, cookie_id, user_id, item_id, "user", message, intent)
ai_reply_engine.save_conversation(chat_id, cookie_id, user_id, item_id, "assistant", ai_reply, intent)
# 显示最终统计
print(f"\n📈 最终统计:")
final_count = ai_reply_engine.get_bargain_count(chat_id, cookie_id)
print(f" 总议价轮数: {final_count}")
print(f" 最大允许轮数: {max_rounds}")
print(f" 是否达到限制: {'' if final_count >= max_rounds else ''}")
def show_bargain_features():
"""展示议价功能特性"""
print(f"\n🎯 议价功能特性说明:")
print("=" * 50)
features = [
"✅ 智能议价轮数统计:自动统计用户的议价次数",
"✅ 灵活轮数限制可配置最大议价轮数1-10轮",
"✅ 优惠金额控制:设置最大优惠百分比和金额",
"✅ 友好拒绝回复:超出限制时礼貌拒绝继续议价",
"✅ 上下文感知AI了解完整的议价历史",
"✅ 个性化策略:根据议价轮数调整回复策略",
"✅ 数据持久化:议价记录永久保存",
"✅ 实时生效:配置修改后立即生效"
]
for feature in features:
print(f" {feature}")
print(f"\n💡 使用建议:")
suggestions = [
"设置合理的最大议价轮数建议3-5轮",
"配合最大优惠百分比和金额使用",
"在AI提示词中强调议价策略",
"定期分析议价数据,优化策略",
"根据商品类型调整议价参数"
]
for suggestion in suggestions:
print(f"{suggestion}")
def main():
"""主函数"""
print("🚀 AI回复议价功能演示")
# 模拟议价对话
simulate_bargain_conversation()
# 展示功能特性
show_bargain_features()
print(f"\n🎉 演示完成!")
print(f"\n📋 下一步:")
print(f" 1. 在Web界面配置真实的AI API密钥")
print(f" 2. 为需要的账号启用AI回复功能")
print(f" 3. 设置合适的议价参数")
print(f" 4. 测试实际的议价效果")
if __name__ == "__main__":
main()

View File

@ -81,6 +81,52 @@ class DBManager:
)
''')
# 创建AI回复配置表
cursor.execute('''
CREATE TABLE IF NOT EXISTS ai_reply_settings (
cookie_id TEXT PRIMARY KEY,
ai_enabled BOOLEAN DEFAULT FALSE,
model_name TEXT DEFAULT 'qwen-plus',
api_key TEXT,
base_url TEXT DEFAULT 'https://dashscope.aliyuncs.com/compatible-mode/v1',
max_discount_percent INTEGER DEFAULT 10,
max_discount_amount INTEGER DEFAULT 100,
max_bargain_rounds INTEGER DEFAULT 3,
custom_prompts TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (cookie_id) REFERENCES cookies(id) ON DELETE CASCADE
)
''')
# 创建AI对话历史表
cursor.execute('''
CREATE TABLE IF NOT EXISTS ai_conversations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
cookie_id TEXT NOT NULL,
chat_id TEXT NOT NULL,
user_id TEXT NOT NULL,
item_id TEXT NOT NULL,
role TEXT NOT NULL,
content TEXT NOT NULL,
intent TEXT,
bargain_count INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (cookie_id) REFERENCES cookies (id) ON DELETE CASCADE
)
''')
# 创建AI商品信息缓存表
cursor.execute('''
CREATE TABLE IF NOT EXISTS ai_item_cache (
item_id TEXT PRIMARY KEY,
data TEXT NOT NULL,
price REAL,
description TEXT,
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
# 创建卡券表
cursor.execute('''
CREATE TABLE IF NOT EXISTS cards (
@ -394,6 +440,117 @@ class DBManager:
logger.error(f"获取所有Cookie状态失败: {e}")
return {}
# -------------------- AI回复设置操作 --------------------
def save_ai_reply_settings(self, cookie_id: str, settings: dict) -> bool:
"""保存AI回复设置"""
with self.lock:
try:
cursor = self.conn.cursor()
cursor.execute('''
INSERT OR REPLACE INTO ai_reply_settings
(cookie_id, ai_enabled, model_name, api_key, base_url,
max_discount_percent, max_discount_amount, max_bargain_rounds,
custom_prompts, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
''', (
cookie_id,
settings.get('ai_enabled', False),
settings.get('model_name', 'qwen-plus'),
settings.get('api_key', ''),
settings.get('base_url', 'https://dashscope.aliyuncs.com/compatible-mode/v1'),
settings.get('max_discount_percent', 10),
settings.get('max_discount_amount', 100),
settings.get('max_bargain_rounds', 3),
settings.get('custom_prompts', '')
))
self.conn.commit()
logger.debug(f"AI回复设置保存成功: {cookie_id}")
return True
except Exception as e:
logger.error(f"保存AI回复设置失败: {e}")
self.conn.rollback()
return False
def get_ai_reply_settings(self, cookie_id: str) -> dict:
"""获取AI回复设置"""
with self.lock:
try:
cursor = self.conn.cursor()
cursor.execute('''
SELECT ai_enabled, model_name, api_key, base_url,
max_discount_percent, max_discount_amount, max_bargain_rounds,
custom_prompts
FROM ai_reply_settings WHERE cookie_id = ?
''', (cookie_id,))
result = cursor.fetchone()
if result:
return {
'ai_enabled': bool(result[0]),
'model_name': result[1],
'api_key': result[2],
'base_url': result[3],
'max_discount_percent': result[4],
'max_discount_amount': result[5],
'max_bargain_rounds': result[6],
'custom_prompts': result[7]
}
else:
# 返回默认设置
return {
'ai_enabled': False,
'model_name': 'qwen-plus',
'api_key': '',
'base_url': 'https://dashscope.aliyuncs.com/compatible-mode/v1',
'max_discount_percent': 10,
'max_discount_amount': 100,
'max_bargain_rounds': 3,
'custom_prompts': ''
}
except Exception as e:
logger.error(f"获取AI回复设置失败: {e}")
return {
'ai_enabled': False,
'model_name': 'qwen-plus',
'api_key': '',
'base_url': 'https://dashscope.aliyuncs.com/compatible-mode/v1',
'max_discount_percent': 10,
'max_discount_amount': 100,
'max_bargain_rounds': 3,
'custom_prompts': ''
}
def get_all_ai_reply_settings(self) -> Dict[str, dict]:
"""获取所有账号的AI回复设置"""
with self.lock:
try:
cursor = self.conn.cursor()
cursor.execute('''
SELECT cookie_id, ai_enabled, model_name, api_key, base_url,
max_discount_percent, max_discount_amount, max_bargain_rounds,
custom_prompts
FROM ai_reply_settings
''')
result = {}
for row in cursor.fetchall():
cookie_id = row[0]
result[cookie_id] = {
'ai_enabled': bool(row[1]),
'model_name': row[2],
'api_key': row[3],
'base_url': row[4],
'max_discount_percent': row[5],
'max_discount_amount': row[6],
'max_bargain_rounds': row[7],
'custom_prompts': row[8]
}
return result
except Exception as e:
logger.error(f"获取所有AI回复设置失败: {e}")
return {}
# -------------------- 默认回复操作 --------------------
def save_default_reply(self, cookie_id: str, enabled: bool, reply_content: str = None):
"""保存默认回复设置"""
@ -693,7 +850,8 @@ class DBManager:
tables = [
'cookies', 'keywords', 'cookie_status', 'cards',
'delivery_rules', 'default_replies', 'notification_channels',
'message_notifications', 'system_settings', 'item_info'
'message_notifications', 'system_settings', 'item_info',
'ai_reply_settings', 'ai_conversations', 'ai_item_cache'
]
for table in tables:
@ -729,7 +887,8 @@ class DBManager:
# 注意:按照外键依赖关系的逆序删除
tables = [
'message_notifications', 'notification_channels', 'default_replies',
'delivery_rules', 'cards', 'item_info', 'cookie_status', 'keywords', 'cookies'
'delivery_rules', 'cards', 'item_info', 'cookie_status', 'keywords',
'ai_conversations', 'ai_reply_settings', 'ai_item_cache', 'cookies'
]
for table in tables:
@ -743,7 +902,8 @@ class DBManager:
for table_name, table_data in data.items():
if table_name not in ['cookies', 'keywords', 'cookie_status', 'cards',
'delivery_rules', 'default_replies', 'notification_channels',
'message_notifications', 'system_settings', 'item_info']:
'message_notifications', 'system_settings', 'item_info',
'ai_reply_settings', 'ai_conversations', 'ai_item_cache']:
continue
columns = table_data['columns']

View File

@ -1,298 +0,0 @@
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion
:: 闲鱼自动回复系统 Docker 部署脚本 (Windows版本)
:: 作者: Xianyu Auto Reply System
:: 版本: 1.0.0
title 闲鱼自动回复系统 Docker 部署
:: 颜色定义
set "RED=[91m"
set "GREEN=[92m"
set "YELLOW=[93m"
set "BLUE=[94m"
set "NC=[0m"
:: 打印带颜色的消息
:print_info
echo %BLUE%[INFO]%NC% %~1
goto :eof
:print_success
echo %GREEN%[SUCCESS]%NC% %~1
goto :eof
:print_warning
echo %YELLOW%[WARNING]%NC% %~1
goto :eof
:print_error
echo %RED%[ERROR]%NC% %~1
goto :eof
:: 检查Docker是否安装
:check_docker
call :print_info "检查 Docker 环境..."
docker --version >nul 2>&1
if errorlevel 1 (
call :print_error "Docker 未安装,请先安装 Docker Desktop"
echo.
echo 下载地址: https://www.docker.com/products/docker-desktop
pause
exit /b 1
)
docker-compose --version >nul 2>&1
if errorlevel 1 (
call :print_error "Docker Compose 未安装,请先安装 Docker Compose"
pause
exit /b 1
)
call :print_success "Docker 环境检查通过"
goto :eof
:: 创建必要的目录
:create_directories
call :print_info "创建必要的目录..."
if not exist "data" mkdir data
if not exist "logs" mkdir logs
if not exist "backups" mkdir backups
if not exist "nginx" mkdir nginx
if not exist "nginx\ssl" mkdir nginx\ssl
REM 检查目录是否创建成功
if not exist "data" (
call :print_error "data目录创建失败"
pause
exit /b 1
)
if not exist "logs" (
call :print_error "logs目录创建失败"
pause
exit /b 1
)
call :print_success "目录创建完成"
goto :eof
:: 生成默认配置文件
:generate_config
REM 生成.env文件
if not exist ".env" (
if exist ".env.example" (
call :print_info "从模板生成 .env 文件..."
copy ".env.example" ".env" >nul
call :print_success ".env 文件已生成"
) else (
call :print_warning ".env.example 文件不存在,跳过 .env 文件生成"
)
) else (
call :print_info ".env 文件已存在,跳过生成"
)
REM 生成global_config.yml文件
if exist "global_config.yml" (
call :print_info "配置文件已存在,跳过生成"
goto :eof
)
call :print_info "生成默认配置文件..."
(
echo # 闲鱼自动回复系统配置文件
echo API_ENDPOINTS:
echo login_check: https://passport.goofish.com/newlogin/hasLogin.do
echo message_headinfo: https://h5api.m.goofish.com/h5/mtop.idle.trade.pc.message.headinfo/1.0/
echo token: https://h5api.m.goofish.com/h5/mtop.taobao.idlemessage.pc.login.token/1.0/
echo.
echo APP_CONFIG:
echo api_version: '1.0'
echo app_key: 444e9908a51d1cb236a27862abc769c9
echo app_version: '1.0'
echo platform: web
echo.
echo AUTO_REPLY:
echo enabled: true
echo default_message: '亲爱的"{send_user_name}" 老板你好!所有宝贝都可以拍,秒发货的哈~不满意的话可以直接申请退款哈~'
echo max_retry: 3
echo retry_interval: 5
echo api:
echo enabled: false
echo host: 0.0.0.0 # 绑定所有网络接口支持IP访问
echo port: 8080 # Web服务端口
echo url: http://0.0.0.0:8080/xianyu/reply
echo timeout: 10
echo.
echo COOKIES:
echo last_update_time: ''
echo value: ''
echo.
echo DEFAULT_HEADERS:
echo accept: application/json
echo accept-language: zh-CN,zh;q=0.9
echo cache-control: no-cache
echo origin: https://www.goofish.com
echo pragma: no-cache
echo referer: https://www.goofish.com/
echo user-agent: Mozilla/5.0 ^(Windows NT 10.0; Win64; x64^) AppleWebKit/537.36 ^(KHTML, like Gecko^) Chrome/119.0.0.0 Safari/537.36
echo.
echo WEBSOCKET_URL: wss://wss-goofish.dingtalk.com/
echo HEARTBEAT_INTERVAL: 15
echo HEARTBEAT_TIMEOUT: 5
echo TOKEN_REFRESH_INTERVAL: 3600
echo TOKEN_RETRY_INTERVAL: 300
echo MESSAGE_EXPIRE_TIME: 300000
echo.
echo LOG_CONFIG:
echo level: INFO
echo format: '{time:YYYY-MM-DD HH:mm:ss.SSS} | {level} | {name}:{function}:{line} - {message}'
echo rotation: '1 day'
echo retention: '7 days'
) > global_config.yml
call :print_success "默认配置文件已生成"
goto :eof
:: 构建Docker镜像
:build_image
call :print_info "构建 Docker 镜像..."
docker build -t xianyu-auto-reply:latest .
if errorlevel 1 (
call :print_error "Docker 镜像构建失败"
pause
exit /b 1
)
call :print_success "Docker 镜像构建完成"
goto :eof
:: 启动服务
:start_services
call :print_info "启动服务..."
if "%~1"=="--with-nginx" (
call :print_info "启动服务(包含 Nginx..."
docker-compose --profile with-nginx up -d
) else (
call :print_info "启动服务(不包含 Nginx..."
docker-compose up -d
)
if errorlevel 1 (
call :print_error "服务启动失败"
pause
exit /b 1
)
call :print_success "服务启动完成"
goto :eof
:: 显示服务状态
:show_status
call :print_info "服务状态:"
docker-compose ps
echo.
call :print_info "服务日志最近10行"
docker-compose logs --tail=10
goto :eof
:: 显示访问信息
:show_access_info
call :print_success "部署完成!"
echo.
call :print_info "访问信息:"
echo Web界面: http://localhost:8080
echo 默认账号: admin
echo 默认密码: admin123
echo.
call :print_info "常用命令:"
echo 查看日志: docker-compose logs -f
echo 重启服务: docker-compose restart
echo 停止服务: docker-compose down
echo 更新服务: deploy.bat update
echo.
call :print_info "数据目录:"
echo 数据库: .\data\xianyu_data.db
echo 日志: .\logs\
echo 配置: .\global_config.yml
echo.
goto :eof
:: 更新服务
:update_services
call :print_info "更新服务..."
docker-compose down
call :build_image
call :start_services %~1
call :print_success "服务更新完成"
goto :eof
:: 清理资源
:cleanup
call :print_warning "清理 Docker 资源..."
docker-compose down --volumes --remove-orphans
docker rmi xianyu-auto-reply:latest 2>nul
call :print_success "清理完成"
goto :eof
:: 显示帮助
:show_help
echo 使用方法:
echo %~nx0 # 首次部署
echo %~nx0 with-nginx # 部署并启动 Nginx
echo %~nx0 update # 更新服务
echo %~nx0 update with-nginx # 更新服务并启动 Nginx
echo %~nx0 status # 查看服务状态
echo %~nx0 cleanup # 清理所有资源
echo %~nx0 help # 显示帮助
goto :eof
:: 主函数
:main
echo ========================================
echo 闲鱼自动回复系统 Docker 部署脚本
echo ========================================
echo.
if "%~1"=="update" (
call :print_info "更新模式"
call :check_docker
call :update_services %~2
call :show_status
call :show_access_info
) else if "%~1"=="cleanup" (
call :print_warning "清理模式"
call :cleanup
) else if "%~1"=="status" (
call :show_status
) else if "%~1"=="help" (
call :show_help
) else (
call :print_info "首次部署模式"
call :check_docker
call :create_directories
call :generate_config
call :build_image
call :start_services %~1
call :show_status
call :show_access_info
)
echo.
pause
goto :eof
:: 执行主函数
call :main %*

View File

@ -36,6 +36,12 @@ services:
- AUTO_DELIVERY_TIMEOUT=${AUTO_DELIVERY_TIMEOUT:-30}
- API_CARD_TIMEOUT=${API_CARD_TIMEOUT:-10}
- BATCH_DATA_LOCK_TIMEOUT=${BATCH_DATA_LOCK_TIMEOUT:-5}
# AI回复相关配置
- AI_REPLY_ENABLED=${AI_REPLY_ENABLED:-false}
- DEFAULT_AI_MODEL=${DEFAULT_AI_MODEL:-qwen-plus}
- DEFAULT_AI_BASE_URL=${DEFAULT_AI_BASE_URL:-https://dashscope.aliyuncs.com/compatible-mode/v1}
- AI_REQUEST_TIMEOUT=${AI_REQUEST_TIMEOUT:-30}
- AI_MAX_TOKENS=${AI_MAX_TOKENS:-100}
- WEBSOCKET_URL=${WEBSOCKET_URL:-wss://wss-goofish.dingtalk.com/}
- HEARTBEAT_INTERVAL=${HEARTBEAT_INTERVAL:-15}
- HEARTBEAT_TIMEOUT=${HEARTBEAT_TIMEOUT:-5}

View File

@ -1,301 +0,0 @@
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion
:: 闲鱼自动回复系统 Docker 部署脚本 (Windows版本)
:: 支持快速部署和管理
set PROJECT_NAME=xianyu-auto-reply
set COMPOSE_FILE=docker-compose.yml
set ENV_FILE=.env
:: 颜色定义 (Windows 10+ 支持ANSI颜色)
set "RED=[31m"
set "GREEN=[32m"
set "YELLOW=[33m"
set "BLUE=[34m"
set "NC=[0m"
:: 打印带颜色的消息
:print_info
echo %BLUE% %~1%NC%
goto :eof
:print_success
echo %GREEN%%~1%NC%
goto :eof
:print_warning
echo %YELLOW%⚠️ %~1%NC%
goto :eof
:print_error
echo %RED%%~1%NC%
goto :eof
:: 检查依赖
:check_dependencies
call :print_info "检查系统依赖..."
docker --version >nul 2>&1
if errorlevel 1 (
call :print_error "Docker 未安装,请先安装 Docker Desktop"
exit /b 1
)
docker-compose --version >nul 2>&1
if errorlevel 1 (
call :print_error "Docker Compose 未安装,请先安装 Docker Compose"
exit /b 1
)
call :print_success "系统依赖检查通过"
goto :eof
:: 初始化配置
:init_config
call :print_info "初始化配置文件..."
if not exist "%ENV_FILE%" (
if exist ".env.example" (
copy ".env.example" "%ENV_FILE%" >nul
call :print_success "已创建 %ENV_FILE% 配置文件"
) else (
call :print_error ".env.example 文件不存在"
exit /b 1
)
) else (
call :print_warning "%ENV_FILE% 已存在,跳过创建"
)
:: 创建必要的目录
if not exist "data" mkdir data
if not exist "logs" mkdir logs
if not exist "backups" mkdir backups
call :print_success "已创建必要的目录"
goto :eof
:: 构建镜像
:build_image
call :print_info "构建 Docker 镜像..."
docker-compose build --no-cache
if errorlevel 1 (
call :print_error "镜像构建失败"
exit /b 1
)
call :print_success "镜像构建完成"
goto :eof
:: 启动服务
:start_services
set "profile="
if "%~1"=="with-nginx" (
set "profile=--profile with-nginx"
call :print_info "启动服务(包含 Nginx..."
) else (
call :print_info "启动基础服务..."
)
docker-compose %profile% up -d
if errorlevel 1 (
call :print_error "服务启动失败"
exit /b 1
)
call :print_success "服务启动完成"
:: 等待服务就绪
call :print_info "等待服务就绪..."
timeout /t 10 /nobreak >nul
:: 检查服务状态
docker-compose ps | findstr "Up" >nul
if errorlevel 1 (
call :print_error "服务启动失败"
docker-compose logs
exit /b 1
) else (
call :print_success "服务运行正常"
call :show_access_info "%~1"
)
goto :eof
:: 停止服务
:stop_services
call :print_info "停止服务..."
docker-compose down
call :print_success "服务已停止"
goto :eof
:: 重启服务
:restart_services
call :print_info "重启服务..."
docker-compose restart
call :print_success "服务已重启"
goto :eof
:: 查看日志
:show_logs
if "%~1"=="" (
docker-compose logs -f
) else (
docker-compose logs -f "%~1"
)
goto :eof
:: 查看状态
:show_status
call :print_info "服务状态:"
docker-compose ps
call :print_info "资源使用:"
for /f "tokens=*" %%i in ('docker-compose ps -q') do (
docker stats --no-stream %%i
)
goto :eof
:: 显示访问信息
:show_access_info
echo.
call :print_success "🎉 部署完成!"
echo.
if "%~1"=="with-nginx" (
echo 📱 访问地址:
echo HTTP: http://localhost
echo HTTPS: https://localhost ^(如果配置了SSL^)
) else (
echo 📱 访问地址:
echo HTTP: http://localhost:8080
)
echo.
echo 🔐 默认登录信息:
echo 用户名: admin
echo 密码: admin123
echo.
echo 📊 管理命令:
echo 查看状态: %~nx0 status
echo 查看日志: %~nx0 logs
echo 重启服务: %~nx0 restart
echo 停止服务: %~nx0 stop
echo.
goto :eof
:: 健康检查
:health_check
call :print_info "执行健康检查..."
set "url=http://localhost:8080/health"
set "max_attempts=30"
set "attempt=1"
:health_loop
curl -f -s "%url%" >nul 2>&1
if not errorlevel 1 (
call :print_success "健康检查通过"
goto :eof
)
call :print_info "等待服务就绪... (!attempt!/%max_attempts%)"
timeout /t 2 /nobreak >nul
set /a attempt+=1
if !attempt! leq %max_attempts% goto health_loop
call :print_error "健康检查失败"
exit /b 1
:: 备份数据
:backup_data
call :print_info "备份数据..."
for /f "tokens=2 delims==" %%i in ('wmic OS Get localdatetime /value') do set datetime=%%i
set backup_dir=backups\%datetime:~0,8%_%datetime:~8,6%
mkdir "%backup_dir%" 2>nul
:: 备份数据库
if exist "data\xianyu_data.db" (
copy "data\xianyu_data.db" "%backup_dir%\" >nul
call :print_success "数据库备份完成"
)
:: 备份配置
copy "%ENV_FILE%" "%backup_dir%\" >nul
copy "global_config.yml" "%backup_dir%\" >nul 2>&1
call :print_success "数据备份完成: %backup_dir%"
goto :eof
:: 显示帮助信息
:show_help
echo 闲鱼自动回复系统 Docker 部署脚本 ^(Windows版本^)
echo.
echo 用法: %~nx0 [命令] [选项]
echo.
echo 命令:
echo init 初始化配置文件
echo build 构建 Docker 镜像
echo start [with-nginx] 启动服务^(可选包含 Nginx^)
echo stop 停止服务
echo restart 重启服务
echo status 查看服务状态
echo logs [service] 查看日志
echo health 健康检查
echo backup 备份数据
echo help 显示帮助信息
echo.
echo 示例:
echo %~nx0 init # 初始化配置
echo %~nx0 start # 启动基础服务
echo %~nx0 start with-nginx # 启动包含 Nginx 的服务
echo %~nx0 logs xianyu-app # 查看应用日志
echo.
goto :eof
:: 主函数
:main
if "%~1"=="init" (
call :check_dependencies
call :init_config
) else if "%~1"=="build" (
call :check_dependencies
call :build_image
) else if "%~1"=="start" (
call :check_dependencies
call :init_config
call :build_image
call :start_services "%~2"
) else if "%~1"=="stop" (
call :stop_services
) else if "%~1"=="restart" (
call :restart_services
) else if "%~1"=="status" (
call :show_status
) else if "%~1"=="logs" (
call :show_logs "%~2"
) else if "%~1"=="health" (
call :health_check
) else if "%~1"=="backup" (
call :backup_data
) else if "%~1"=="help" (
call :show_help
) else if "%~1"=="-h" (
call :show_help
) else if "%~1"=="--help" (
call :show_help
) else if "%~1"=="" (
call :print_info "快速部署模式"
call :check_dependencies
call :init_config
call :build_image
call :start_services
) else (
call :print_error "未知命令: %~1"
call :show_help
exit /b 1
)
goto :eof
:: 执行主函数
call :main %*

View File

@ -1,350 +0,0 @@
#!/bin/bash
# 闲鱼自动回复系统 Docker 部署脚本
# 支持快速部署和管理
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 项目配置
PROJECT_NAME="xianyu-auto-reply"
COMPOSE_FILE="docker-compose.yml"
ENV_FILE=".env"
# 打印带颜色的消息
print_info() {
echo -e "${BLUE} $1${NC}"
}
print_success() {
echo -e "${GREEN}$1${NC}"
}
print_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
print_error() {
echo -e "${RED}$1${NC}"
}
# 检查依赖
check_dependencies() {
print_info "检查系统依赖..."
if ! command -v docker &> /dev/null; then
print_error "Docker 未安装,请先安装 Docker"
exit 1
fi
if ! command -v docker-compose &> /dev/null; then
print_error "Docker Compose 未安装,请先安装 Docker Compose"
exit 1
fi
print_success "系统依赖检查通过"
}
# 初始化配置
init_config() {
print_info "初始化配置文件..."
if [ ! -f "$ENV_FILE" ]; then
if [ -f ".env.example" ]; then
cp .env.example "$ENV_FILE"
print_success "已创建 $ENV_FILE 配置文件"
else
print_error ".env.example 文件不存在"
exit 1
fi
else
print_warning "$ENV_FILE 已存在,跳过创建"
fi
# 创建必要的目录
mkdir -p data logs backups
print_success "已创建必要的目录"
}
# 构建镜像
build_image() {
print_info "构建 Docker 镜像..."
docker-compose build --no-cache
print_success "镜像构建完成"
}
# 启动服务
start_services() {
local profile=""
if [ "$1" = "with-nginx" ]; then
profile="--profile with-nginx"
print_info "启动服务(包含 Nginx..."
else
print_info "启动基础服务..."
fi
docker-compose $profile up -d
print_success "服务启动完成"
# 等待服务就绪
print_info "等待服务就绪..."
sleep 10
# 检查服务状态
if docker-compose ps | grep -q "Up"; then
print_success "服务运行正常"
show_access_info "$1"
else
print_error "服务启动失败"
docker-compose logs
exit 1
fi
}
# 停止服务
stop_services() {
print_info "停止服务..."
docker-compose down
print_success "服务已停止"
}
# 重启服务
restart_services() {
print_info "重启服务..."
docker-compose restart
print_success "服务已重启"
}
# 查看日志
show_logs() {
local service="$1"
if [ -z "$service" ]; then
docker-compose logs -f
else
docker-compose logs -f "$service"
fi
}
# 查看状态
show_status() {
print_info "服务状态:"
docker-compose ps
print_info "资源使用:"
docker stats --no-stream $(docker-compose ps -q)
}
# 显示访问信息
show_access_info() {
local with_nginx="$1"
echo ""
print_success "🎉 部署完成!"
echo ""
if [ "$with_nginx" = "with-nginx" ]; then
echo "📱 访问地址:"
echo " HTTP: http://localhost"
echo " HTTPS: https://localhost (如果配置了SSL)"
else
echo "📱 访问地址:"
echo " HTTP: http://localhost:8080"
fi
echo ""
echo "🔐 默认登录信息:"
echo " 用户名: admin"
echo " 密码: admin123"
echo ""
echo "📊 管理命令:"
echo " 查看状态: $0 status"
echo " 查看日志: $0 logs"
echo " 重启服务: $0 restart"
echo " 停止服务: $0 stop"
echo ""
}
# 健康检查
health_check() {
print_info "执行健康检查..."
local url="http://localhost:8080/health"
local max_attempts=30
local attempt=1
while [ $attempt -le $max_attempts ]; do
if curl -f -s "$url" > /dev/null 2>&1; then
print_success "健康检查通过"
return 0
fi
print_info "等待服务就绪... ($attempt/$max_attempts)"
sleep 2
((attempt++))
done
print_error "健康检查失败"
return 1
}
# 备份数据
backup_data() {
print_info "备份数据..."
local backup_dir="backups/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$backup_dir"
# 备份数据库
if [ -f "data/xianyu_data.db" ]; then
cp data/xianyu_data.db "$backup_dir/"
print_success "数据库备份完成"
fi
# 备份配置
cp "$ENV_FILE" "$backup_dir/"
cp global_config.yml "$backup_dir/" 2>/dev/null || true
print_success "数据备份完成: $backup_dir"
}
# 更新部署
update_deployment() {
print_info "更新部署..."
# 备份数据
backup_data
# 停止服务
stop_services
# 拉取最新代码如果是git仓库
if [ -d ".git" ]; then
print_info "拉取最新代码..."
git pull
fi
# 重新构建
build_image
# 启动服务
start_services
print_success "更新完成"
}
# 清理环境
cleanup() {
print_warning "这将删除所有容器、镜像和数据,确定要继续吗?(y/N)"
read -r response
if [[ "$response" =~ ^[Yy]$ ]]; then
print_info "清理环境..."
# 停止并删除容器
docker-compose down -v --rmi all
# 删除数据目录
rm -rf data logs backups
print_success "环境清理完成"
else
print_info "取消清理操作"
fi
}
# 显示帮助信息
show_help() {
echo "闲鱼自动回复系统 Docker 部署脚本"
echo ""
echo "用法: $0 [命令] [选项]"
echo ""
echo "命令:"
echo " init 初始化配置文件"
echo " build 构建 Docker 镜像"
echo " start [with-nginx] 启动服务(可选包含 Nginx"
echo " stop 停止服务"
echo " restart 重启服务"
echo " status 查看服务状态"
echo " logs [service] 查看日志"
echo " health 健康检查"
echo " backup 备份数据"
echo " update 更新部署"
echo " cleanup 清理环境"
echo " help 显示帮助信息"
echo ""
echo "示例:"
echo " $0 init # 初始化配置"
echo " $0 start # 启动基础服务"
echo " $0 start with-nginx # 启动包含 Nginx 的服务"
echo " $0 logs xianyu-app # 查看应用日志"
echo ""
}
# 主函数
main() {
case "$1" in
"init")
check_dependencies
init_config
;;
"build")
check_dependencies
build_image
;;
"start")
check_dependencies
init_config
build_image
start_services "$2"
;;
"stop")
stop_services
;;
"restart")
restart_services
;;
"status")
show_status
;;
"logs")
show_logs "$2"
;;
"health")
health_check
;;
"backup")
backup_data
;;
"update")
check_dependencies
update_deployment
;;
"cleanup")
cleanup
;;
"help"|"--help"|"-h")
show_help
;;
"")
print_info "快速部署模式"
check_dependencies
init_config
build_image
start_services
;;
*)
print_error "未知命令: $1"
show_help
exit 1
;;
esac
}
# 执行主函数
main "$@"

View File

@ -1,156 +0,0 @@
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion
:: 修复数据库权限问题的脚本 (Windows版本)
:: 解决Docker容器中数据库无法创建的问题
title 数据库权限修复脚本
:: 颜色定义
set "RED=[91m"
set "GREEN=[92m"
set "YELLOW=[93m"
set "BLUE=[94m"
set "NC=[0m"
:: 打印带颜色的消息
:print_info
echo %BLUE%[INFO]%NC% %~1
goto :eof
:print_success
echo %GREEN%[SUCCESS]%NC% %~1
goto :eof
:print_warning
echo %YELLOW%[WARNING]%NC% %~1
goto :eof
:print_error
echo %RED%[ERROR]%NC% %~1
goto :eof
echo ========================================
echo 数据库权限修复脚本
echo ========================================
echo.
:: 1. 停止现有容器
call :print_info "停止现有容器..."
docker-compose down >nul 2>&1
:: 2. 检查并创建目录
call :print_info "检查并创建必要目录..."
for %%d in (data logs backups) do (
if not exist "%%d" (
call :print_info "创建目录: %%d"
mkdir "%%d"
)
if not exist "%%d" (
call :print_error "目录 %%d 创建失败"
pause
exit /b 1
)
call :print_success "目录 %%d 权限正常"
)
:: 3. 检查现有数据库文件
if exist "data\xianyu_data.db" (
call :print_info "检查现有数据库文件..."
call :print_success "数据库文件存在"
) else (
call :print_info "数据库文件不存在,将在启动时创建"
)
:: 4. 测试数据库创建
call :print_info "测试数据库创建..."
python -c "
import sqlite3
import os
db_path = 'data/test_db.sqlite'
try:
conn = sqlite3.connect(db_path)
conn.execute('CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY)')
conn.commit()
conn.close()
print('✅ 数据库创建测试成功')
if os.path.exists(db_path):
os.remove(db_path)
except Exception as e:
print(f'❌ 数据库创建测试失败: {e}')
exit(1)
"
if !errorlevel! neq 0 (
call :print_error "数据库创建测试失败"
pause
exit /b 1
)
:: 5. 重新构建并启动
call :print_info "重新构建并启动服务..."
docker-compose build --no-cache
if !errorlevel! neq 0 (
call :print_error "Docker镜像构建失败"
pause
exit /b 1
)
docker-compose up -d
if !errorlevel! neq 0 (
call :print_error "服务启动失败"
pause
exit /b 1
)
:: 6. 等待服务启动
call :print_info "等待服务启动..."
timeout /t 15 /nobreak >nul
:: 7. 检查服务状态
call :print_info "检查服务状态..."
docker-compose ps | findstr "Up" >nul
if !errorlevel! equ 0 (
call :print_success "服务启动成功"
:: 检查日志
call :print_info "检查启动日志..."
docker-compose logs --tail=20 xianyu-app
:: 测试健康检查
call :print_info "测试健康检查..."
timeout /t 5 /nobreak >nul
curl -f http://localhost:8080/health >nul 2>&1
if !errorlevel! equ 0 (
call :print_success "健康检查通过"
) else (
call :print_warning "健康检查失败,但服务可能仍在启动中"
)
) else (
call :print_error "服务启动失败"
call :print_info "查看错误日志:"
docker-compose logs xianyu-app
pause
exit /b 1
)
echo.
call :print_success "数据库权限修复完成!"
echo.
call :print_info "服务信息:"
echo Web界面: http://localhost:8080
echo 健康检查: http://localhost:8080/health
echo 默认账号: admin / admin123
echo.
call :print_info "常用命令:"
echo 查看日志: docker-compose logs -f
echo 重启服务: docker-compose restart
echo 停止服务: docker-compose down
echo.
pause

View File

@ -1,167 +0,0 @@
#!/bin/bash
# 修复数据库权限问题的脚本
# 解决Docker容器中数据库无法创建的问题
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
print_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
echo "========================================"
echo " 数据库权限修复脚本"
echo "========================================"
echo ""
# 1. 停止现有容器
print_info "停止现有容器..."
docker-compose down 2>/dev/null || true
# 2. 检查并创建目录
print_info "检查并创建必要目录..."
for dir in data logs backups; do
if [ ! -d "$dir" ]; then
print_info "创建目录: $dir"
mkdir -p "$dir"
fi
# 设置权限
chmod 755 "$dir"
# 检查权限
if [ ! -w "$dir" ]; then
print_error "目录 $dir 没有写权限"
# 尝试修复权限
print_info "尝试修复权限..."
sudo chmod 755 "$dir" 2>/dev/null || {
print_error "无法修复权限,请手动执行: sudo chmod 755 $dir"
exit 1
}
fi
print_success "目录 $dir 权限正常"
done
# 3. 检查现有数据库文件
if [ -f "data/xianyu_data.db" ]; then
print_info "检查现有数据库文件权限..."
if [ ! -w "data/xianyu_data.db" ]; then
print_warning "数据库文件没有写权限,尝试修复..."
chmod 644 "data/xianyu_data.db"
print_success "数据库文件权限已修复"
else
print_success "数据库文件权限正常"
fi
fi
# 4. 检查Docker用户映射
print_info "检查Docker用户映射..."
CURRENT_UID=$(id -u)
CURRENT_GID=$(id -g)
print_info "当前用户 UID:GID = $CURRENT_UID:$CURRENT_GID"
# 5. 创建测试数据库
print_info "测试数据库创建..."
python3 -c "
import sqlite3
import os
db_path = 'data/test_db.sqlite'
try:
conn = sqlite3.connect(db_path)
conn.execute('CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY)')
conn.commit()
conn.close()
print('✅ 数据库创建测试成功')
os.remove(db_path)
except Exception as e:
print(f'❌ 数据库创建测试失败: {e}')
exit(1)
" || {
print_error "数据库创建测试失败"
exit 1
}
# 6. 更新docker-compose.yml用户映射
print_info "检查docker-compose.yml用户映射..."
if ! grep -q "user:" docker-compose.yml; then
print_info "添加用户映射到docker-compose.yml..."
# 备份原文件
cp docker-compose.yml docker-compose.yml.backup
# 在xianyu-app服务中添加user配置
sed -i '/container_name: xianyu-auto-reply/a\ user: "'$CURRENT_UID':'$CURRENT_GID'"' docker-compose.yml
print_success "用户映射已添加"
else
print_info "用户映射已存在"
fi
# 7. 重新构建并启动
print_info "重新构建并启动服务..."
docker-compose build --no-cache
docker-compose up -d
# 8. 等待服务启动
print_info "等待服务启动..."
sleep 10
# 9. 检查服务状态
print_info "检查服务状态..."
if docker-compose ps | grep -q "Up"; then
print_success "服务启动成功"
# 检查日志
print_info "检查启动日志..."
docker-compose logs --tail=20 xianyu-app
# 测试健康检查
print_info "测试健康检查..."
sleep 5
if curl -f http://localhost:8080/health >/dev/null 2>&1; then
print_success "健康检查通过"
else
print_warning "健康检查失败,但服务可能仍在启动中"
fi
else
print_error "服务启动失败"
print_info "查看错误日志:"
docker-compose logs xianyu-app
exit 1
fi
echo ""
print_success "数据库权限修复完成!"
echo ""
print_info "服务信息:"
echo " Web界面: http://localhost:8080"
echo " 健康检查: http://localhost:8080/health"
echo " 默认账号: admin / admin123"
echo ""
print_info "常用命令:"
echo " 查看日志: docker-compose logs -f"
echo " 重启服务: docker-compose restart"
echo " 停止服务: docker-compose down"

View File

@ -1,144 +0,0 @@
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion
:: 修复Docker部署警告的快速脚本 (Windows版本)
:: 解决version过时和.env文件缺失问题
title Docker部署警告修复脚本
:: 颜色定义
set "RED=[91m"
set "GREEN=[92m"
set "YELLOW=[93m"
set "BLUE=[94m"
set "NC=[0m"
:: 打印带颜色的消息
:print_info
echo %BLUE%[INFO]%NC% %~1
goto :eof
:print_success
echo %GREEN%[SUCCESS]%NC% %~1
goto :eof
:print_warning
echo %YELLOW%[WARNING]%NC% %~1
goto :eof
:print_error
echo %RED%[ERROR]%NC% %~1
goto :eof
echo ========================================
echo Docker部署警告修复脚本
echo ========================================
echo.
:: 1. 检查并创建.env文件
call :print_info "检查 .env 文件..."
if not exist ".env" (
if exist ".env.example" (
call :print_info "从 .env.example 创建 .env 文件..."
copy ".env.example" ".env" >nul
call :print_success ".env 文件已创建"
) else (
call :print_warning ".env.example 文件不存在"
call :print_info "创建基本的 .env 文件..."
(
echo # 闲鱼自动回复系统 Docker 环境变量配置文件
echo.
echo # 基础配置
echo TZ=Asia/Shanghai
echo PYTHONUNBUFFERED=1
echo LOG_LEVEL=INFO
echo.
echo # 数据库配置
echo DB_PATH=/app/data/xianyu_data.db
echo.
echo # 服务配置
echo WEB_PORT=8080
echo.
echo # 安全配置
echo ADMIN_USERNAME=admin
echo ADMIN_PASSWORD=admin123
echo JWT_SECRET_KEY=xianyu-auto-reply-secret-key-2024
echo.
echo # 资源限制
echo MEMORY_LIMIT=512
echo CPU_LIMIT=0.5
echo MEMORY_RESERVATION=256
echo CPU_RESERVATION=0.25
echo.
echo # 自动回复配置
echo AUTO_REPLY_ENABLED=true
echo WEBSOCKET_URL=wss://wss-goofish.dingtalk.com/
echo HEARTBEAT_INTERVAL=15
echo TOKEN_REFRESH_INTERVAL=3600
) > .env
call :print_success "基本 .env 文件已创建"
)
) else (
call :print_success ".env 文件已存在"
)
:: 2. 检查docker-compose.yml版本问题
call :print_info "检查 docker-compose.yml 配置..."
findstr /B "version:" docker-compose.yml >nul 2>&1
if !errorlevel! equ 0 (
call :print_warning "发现过时的 version 字段"
call :print_info "移除 version 字段..."
REM 备份原文件
copy docker-compose.yml docker-compose.yml.backup >nul
REM 创建临时文件移除version行
(
for /f "tokens=*" %%a in (docker-compose.yml) do (
echo %%a | findstr /B "version:" >nul
if !errorlevel! neq 0 (
echo %%a
)
)
) > docker-compose.yml.tmp
REM 替换原文件
move docker-compose.yml.tmp docker-compose.yml >nul
call :print_success "已移除过时的 version 字段"
call :print_info "原文件已备份为 docker-compose.yml.backup"
) else (
call :print_success "docker-compose.yml 配置正确"
)
:: 3. 验证修复结果
call :print_info "验证修复结果..."
echo.
call :print_info "测试 Docker Compose 配置..."
docker-compose config >nul 2>&1
if !errorlevel! equ 0 (
call :print_success "Docker Compose 配置验证通过"
) else (
call :print_error "Docker Compose 配置验证失败"
echo 请检查 docker-compose.yml 文件
pause
exit /b 1
)
echo.
call :print_success "所有警告已修复!"
echo.
call :print_info "现在可以正常使用以下命令:"
echo docker-compose up -d # 启动服务
echo docker-compose ps # 查看状态
echo docker-compose logs -f # 查看日志
echo.
call :print_info "如果需要恢复原配置:"
echo move docker-compose.yml.backup docker-compose.yml
echo.
pause

View File

@ -1,145 +0,0 @@
#!/bin/bash
# 修复Docker部署警告的快速脚本
# 解决version过时和.env文件缺失问题
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
print_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
echo "========================================"
echo " Docker部署警告修复脚本"
echo "========================================"
echo ""
# 1. 检查并创建.env文件
print_info "检查 .env 文件..."
if [ ! -f ".env" ]; then
if [ -f ".env.example" ]; then
print_info "从 .env.example 创建 .env 文件..."
cp .env.example .env
print_success ".env 文件已创建"
else
print_warning ".env.example 文件不存在"
print_info "创建基本的 .env 文件..."
cat > .env << 'EOF'
# 闲鱼自动回复系统 Docker 环境变量配置文件
# 基础配置
TZ=Asia/Shanghai
PYTHONUNBUFFERED=1
LOG_LEVEL=INFO
# 数据库配置
DB_PATH=/app/data/xianyu_data.db
# 服务配置
WEB_PORT=8080
# 安全配置
ADMIN_USERNAME=admin
ADMIN_PASSWORD=admin123
JWT_SECRET_KEY=xianyu-auto-reply-secret-key-2024
# 资源限制
MEMORY_LIMIT=512
CPU_LIMIT=0.5
MEMORY_RESERVATION=256
CPU_RESERVATION=0.25
# 自动回复配置
AUTO_REPLY_ENABLED=true
WEBSOCKET_URL=wss://wss-goofish.dingtalk.com/
HEARTBEAT_INTERVAL=15
TOKEN_REFRESH_INTERVAL=3600
EOF
print_success "基本 .env 文件已创建"
fi
else
print_success ".env 文件已存在"
fi
# 2. 检查docker-compose.yml版本问题
print_info "检查 docker-compose.yml 配置..."
if grep -q "^version:" docker-compose.yml 2>/dev/null; then
print_warning "发现过时的 version 字段"
print_info "移除 version 字段..."
# 备份原文件
cp docker-compose.yml docker-compose.yml.backup
# 移除version行
sed -i '/^version:/d' docker-compose.yml
sed -i '/^$/N;/^\n$/d' docker-compose.yml # 移除空行
print_success "已移除过时的 version 字段"
print_info "原文件已备份为 docker-compose.yml.backup"
else
print_success "docker-compose.yml 配置正确"
fi
# 3. 检查env_file配置
print_info "检查 env_file 配置..."
if grep -A1 "env_file:" docker-compose.yml | grep -q "required: false"; then
print_success "env_file 配置正确"
else
print_info "更新 env_file 配置为可选..."
# 备份文件(如果还没备份)
if [ ! -f "docker-compose.yml.backup" ]; then
cp docker-compose.yml docker-compose.yml.backup
fi
# 更新env_file配置
sed -i '/env_file:/,+1c\
env_file:\
- path: .env\
required: false' docker-compose.yml
print_success "env_file 配置已更新"
fi
# 4. 验证修复结果
print_info "验证修复结果..."
echo ""
print_info "测试 Docker Compose 配置..."
if docker-compose config >/dev/null 2>&1; then
print_success "Docker Compose 配置验证通过"
else
print_error "Docker Compose 配置验证失败"
echo "请检查 docker-compose.yml 文件"
exit 1
fi
echo ""
print_success "所有警告已修复!"
echo ""
print_info "现在可以正常使用以下命令:"
echo " docker-compose up -d # 启动服务"
echo " docker-compose ps # 查看状态"
echo " docker-compose logs -f # 查看日志"
echo ""
print_info "如果需要恢复原配置:"
echo " mv docker-compose.yml.backup docker-compose.yml"

View File

@ -1,121 +0,0 @@
#!/bin/bash
# 快速修复WebSocket兼容性问题
# 解决 "extra_headers" 参数不支持的问题
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
print_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
echo "🔧 WebSocket兼容性问题修复"
echo "================================"
# 1. 检查当前websockets版本
print_info "检查当前websockets版本..."
if command -v python3 &> /dev/null; then
PYTHON_CMD="python3"
elif command -v python &> /dev/null; then
PYTHON_CMD="python"
else
print_error "未找到Python解释器"
exit 1
fi
CURRENT_VERSION=$($PYTHON_CMD -c "import websockets; print(websockets.__version__)" 2>/dev/null || echo "未安装")
print_info "当前websockets版本: $CURRENT_VERSION"
# 2. 测试WebSocket兼容性
print_info "测试WebSocket兼容性..."
$PYTHON_CMD test-websocket-compatibility.py
# 3. 停止现有服务
print_info "停止现有Docker服务..."
docker-compose down 2>/dev/null || true
# 4. 更新websockets版本
print_info "更新websockets版本到兼容版本..."
if [ -f "requirements.txt" ]; then
# 备份原文件
cp requirements.txt requirements.txt.backup
# 更新websockets版本
sed -i 's/websockets>=.*/websockets>=10.0,<13.0 # 兼容性版本范围/' requirements.txt
print_success "requirements.txt已更新"
else
print_warning "requirements.txt文件不存在"
fi
# 5. 重新构建Docker镜像
print_info "重新构建Docker镜像..."
docker-compose build --no-cache
# 6. 启动服务
print_info "启动服务..."
docker-compose up -d
# 7. 等待服务启动
print_info "等待服务启动..."
sleep 15
# 8. 检查服务状态
print_info "检查服务状态..."
if docker-compose ps | grep -q "Up"; then
print_success "✅ 服务启动成功!"
# 检查WebSocket错误
print_info "检查WebSocket连接状态..."
sleep 5
# 查看最近的日志
echo ""
print_info "最近的服务日志:"
docker-compose logs --tail=20 xianyu-app | grep -E "(WebSocket|extra_headers|ERROR)" || echo "未发现WebSocket相关错误"
# 测试健康检查
if curl -f http://localhost:8080/health >/dev/null 2>&1; then
print_success "健康检查通过"
else
print_warning "健康检查失败,服务可能仍在启动中"
fi
else
print_error "❌ 服务启动失败"
print_info "查看错误日志:"
docker-compose logs --tail=30 xianyu-app
exit 1
fi
echo ""
print_success "🎉 WebSocket兼容性问题修复完成"
echo ""
print_info "服务信息:"
echo " Web界面: http://localhost:8080"
echo " 健康检查: http://localhost:8080/health"
echo " 默认账号: admin / admin123"
echo ""
print_info "如果仍有WebSocket问题"
echo " 1. 查看日志: docker-compose logs -f xianyu-app"
echo " 2. 运行测试: python test-websocket-compatibility.py"
echo " 3. 检查网络连接和防火墙设置"

View File

@ -9,11 +9,11 @@ APP_CONFIG:
platform: web
AUTO_REPLY:
api:
enabled: true
enabled: true # 禁用API回复使用AI回复或关键词回复
host: 0.0.0.0 # 绑定所有网络接口支持IP访问
port: 8080 # Web服务端口
timeout: 10
url: http://0.0.0.0:8080/xianyu/reply
url: http://localhost:8080/xianyu/reply # 修复URL地址
default_message: 亲爱的"{send_user_name}" 老板你好!所有宝贝都可以拍,秒发货的哈~不满意的话可以直接申请退款哈~
enabled: true
max_retry: 3

View File

@ -1,116 +0,0 @@
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion
:: 快速修复Docker权限问题 (Windows版本)
title 快速修复Docker权限问题
:: 颜色定义
set "RED=[91m"
set "GREEN=[92m"
set "YELLOW=[93m"
set "BLUE=[94m"
set "NC=[0m"
:print_info
echo %BLUE%[INFO]%NC% %~1
goto :eof
:print_success
echo %GREEN%[SUCCESS]%NC% %~1
goto :eof
:print_error
echo %RED%[ERROR]%NC% %~1
goto :eof
echo 🚀 快速修复Docker权限问题
echo ================================
echo.
:: 1. 停止容器
call :print_info "停止现有容器..."
docker-compose down >nul 2>&1
:: 2. 确保目录存在
call :print_info "创建必要目录..."
if not exist "data" mkdir data
if not exist "logs" mkdir logs
if not exist "backups" mkdir backups
:: 3. 检查并修复docker-compose.yml
call :print_info "检查docker-compose.yml配置..."
findstr /C:"user.*0:0" docker-compose.yml >nul 2>&1
if !errorlevel! neq 0 (
call :print_info "添加root用户配置..."
REM 备份原文件
copy docker-compose.yml docker-compose.yml.backup >nul
REM 创建临时文件添加user配置
(
for /f "tokens=*" %%a in (docker-compose.yml) do (
echo %%a
echo %%a | findstr /C:"container_name: xianyu-auto-reply" >nul
if !errorlevel! equ 0 (
echo user: "0:0"
)
)
) > docker-compose.yml.tmp
REM 替换原文件
move docker-compose.yml.tmp docker-compose.yml >nul
call :print_success "已配置使用root用户运行"
)
:: 4. 重新构建镜像
call :print_info "重新构建Docker镜像..."
docker-compose build --no-cache
if !errorlevel! neq 0 (
call :print_error "Docker镜像构建失败"
pause
exit /b 1
)
:: 5. 启动服务
call :print_info "启动服务..."
docker-compose up -d
if !errorlevel! neq 0 (
call :print_error "服务启动失败"
pause
exit /b 1
)
:: 6. 等待启动
call :print_info "等待服务启动..."
timeout /t 15 /nobreak >nul
:: 7. 检查状态
call :print_info "检查服务状态..."
docker-compose ps | findstr "Up" >nul
if !errorlevel! equ 0 (
call :print_success "✅ 服务启动成功!"
echo.
call :print_info "最近的日志:"
docker-compose logs --tail=10 xianyu-app
echo.
call :print_success "🎉 权限问题已修复!"
echo.
echo 访问信息:
echo Web界面: http://localhost:8080
echo 健康检查: http://localhost:8080/health
echo 默认账号: admin / admin123
) else (
call :print_error "❌ 服务启动失败"
echo.
call :print_info "错误日志:"
docker-compose logs xianyu-app
)
echo.
pause

View File

@ -1,88 +0,0 @@
#!/bin/bash
# 快速修复Docker权限问题
# 这个脚本会立即解决权限问题并重启服务
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
print_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
echo "🚀 快速修复Docker权限问题"
echo "================================"
# 1. 停止容器
print_info "停止现有容器..."
docker-compose down
# 2. 确保目录存在并设置权限
print_info "设置目录权限..."
mkdir -p data logs backups
chmod 777 data logs backups
# 3. 检查并修复docker-compose.yml
print_info "检查docker-compose.yml配置..."
if ! grep -q "user.*0:0" docker-compose.yml; then
print_info "添加root用户配置..."
# 备份原文件
cp docker-compose.yml docker-compose.yml.backup
# 在container_name后添加user配置
sed -i '/container_name: xianyu-auto-reply/a\ user: "0:0"' docker-compose.yml
print_success "已配置使用root用户运行"
fi
# 4. 重新构建镜像
print_info "重新构建Docker镜像..."
docker-compose build --no-cache
# 5. 启动服务
print_info "启动服务..."
docker-compose up -d
# 6. 等待启动
print_info "等待服务启动..."
sleep 15
# 7. 检查状态
print_info "检查服务状态..."
if docker-compose ps | grep -q "Up"; then
print_success "✅ 服务启动成功!"
# 显示日志
echo ""
print_info "最近的日志:"
docker-compose logs --tail=10 xianyu-app
echo ""
print_success "🎉 权限问题已修复!"
echo ""
echo "访问信息:"
echo " Web界面: http://localhost:8080"
echo " 健康检查: http://localhost:8080/health"
echo " 默认账号: admin / admin123"
else
print_error "❌ 服务启动失败"
echo ""
print_info "错误日志:"
docker-compose logs xianyu-app
fi

View File

@ -16,6 +16,7 @@ import uvicorn
import cookie_manager
from db_manager import db_manager
from file_log_collector import setup_file_logging, get_file_log_collector
from ai_reply_engine import ai_reply_engine
# 关键字文件路径
KEYWORDS_FILE = Path(__file__).parent / "回复关键字.txt"
@ -1034,6 +1035,17 @@ class BatchDeleteRequest(BaseModel):
items: List[dict] # [{"cookie_id": "xxx", "item_id": "yyy"}, ...]
class AIReplySettings(BaseModel):
ai_enabled: bool
model_name: str = "qwen-plus"
api_key: str = ""
base_url: str = "https://dashscope.aliyuncs.com/compatible-mode/v1"
max_discount_percent: int = 10
max_discount_amount: int = 100
max_bargain_rounds: int = 3
custom_prompts: str = ""
@app.delete("/items/batch")
def batch_delete_items(
request: BatchDeleteRequest,
@ -1058,6 +1070,110 @@ def batch_delete_items(
raise HTTPException(status_code=500, detail=f"服务器错误: {str(e)}")
# ==================== AI回复管理API ====================
@app.get("/ai-reply-settings/{cookie_id}")
def get_ai_reply_settings(cookie_id: str, _: None = Depends(require_auth)):
"""获取指定账号的AI回复设置"""
try:
settings = db_manager.get_ai_reply_settings(cookie_id)
return settings
except Exception as e:
logger.error(f"获取AI回复设置异常: {e}")
raise HTTPException(status_code=500, detail=f"服务器错误: {str(e)}")
@app.put("/ai-reply-settings/{cookie_id}")
def update_ai_reply_settings(cookie_id: str, settings: AIReplySettings, _: None = Depends(require_auth)):
"""更新指定账号的AI回复设置"""
try:
# 检查账号是否存在
if cookie_manager.manager is None:
raise HTTPException(status_code=500, detail='CookieManager 未就绪')
if cookie_id not in cookie_manager.manager.cookies:
raise HTTPException(status_code=404, detail='账号不存在')
# 保存设置
settings_dict = settings.dict()
success = db_manager.save_ai_reply_settings(cookie_id, settings_dict)
if success:
# 清理客户端缓存,强制重新创建
ai_reply_engine.clear_client_cache(cookie_id)
# 如果启用了AI回复记录日志
if settings.ai_enabled:
logger.info(f"账号 {cookie_id} 启用AI回复")
else:
logger.info(f"账号 {cookie_id} 禁用AI回复")
return {"message": "AI回复设置更新成功"}
else:
raise HTTPException(status_code=400, detail="更新失败")
except HTTPException:
raise
except Exception as e:
logger.error(f"更新AI回复设置异常: {e}")
raise HTTPException(status_code=500, detail=f"服务器错误: {str(e)}")
@app.get("/ai-reply-settings")
def get_all_ai_reply_settings(_: None = Depends(require_auth)):
"""获取所有账号的AI回复设置"""
try:
settings = db_manager.get_all_ai_reply_settings()
return settings
except Exception as e:
logger.error(f"获取所有AI回复设置异常: {e}")
raise HTTPException(status_code=500, detail=f"服务器错误: {str(e)}")
@app.post("/ai-reply-test/{cookie_id}")
def test_ai_reply(cookie_id: str, test_data: dict, _: None = Depends(require_auth)):
"""测试AI回复功能"""
try:
# 检查账号是否存在
if cookie_manager.manager is None:
raise HTTPException(status_code=500, detail='CookieManager 未就绪')
if cookie_id not in cookie_manager.manager.cookies:
raise HTTPException(status_code=404, detail='账号不存在')
# 检查是否启用AI回复
if not ai_reply_engine.is_ai_enabled(cookie_id):
raise HTTPException(status_code=400, detail='该账号未启用AI回复')
# 构造测试数据
test_message = test_data.get('message', '你好')
test_item_info = {
'title': test_data.get('item_title', '测试商品'),
'price': test_data.get('item_price', 100),
'desc': test_data.get('item_desc', '这是一个测试商品')
}
# 生成测试回复
reply = ai_reply_engine.generate_reply(
message=test_message,
item_info=test_item_info,
chat_id=f"test_{int(time.time())}",
cookie_id=cookie_id,
user_id="test_user",
item_id="test_item"
)
if reply:
return {"message": "测试成功", "reply": reply}
else:
raise HTTPException(status_code=400, detail="AI回复生成失败")
except HTTPException:
raise
except Exception as e:
logger.error(f"测试AI回复异常: {e}")
raise HTTPException(status_code=500, detail=f"服务器错误: {str(e)}")
# ==================== 日志管理API ====================
@app.get("/logs")

View File

@ -26,4 +26,8 @@ psutil>=5.9.0
requests>=2.31.0
# 文件上传支持
python-multipart>=0.0.6
python-multipart>=0.0.6
# AI回复相关
openai>=1.65.5
python-dotenv>=1.0.1

View File

@ -631,11 +631,14 @@
.status-badge {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.25rem 0.75rem;
padding: 0.25rem 0.5rem;
border-radius: 12px;
font-size: 0.75rem;
font-size: 0.875rem;
font-weight: 500;
min-width: 2rem;
height: 1.5rem;
}
.status-badge.enabled {
@ -1262,11 +1265,12 @@
<thead>
<tr>
<th style="width: 10%">账号ID</th>
<th style="width: 25%">Cookie值</th>
<th style="width: 10%">关键词</th>
<th style="width: 10%">状态</th>
<th style="width: 12%">默认回复</th>
<th style="width: 33%">操作</th>
<th style="width: 20%">Cookie值</th>
<th style="width: 8%">关键词</th>
<th style="width: 8%">状态</th>
<th style="width: 10%">默认回复</th>
<th style="width: 10%">AI回复</th>
<th style="width: 34%">操作</th>
</tr>
</thead>
<tbody></tbody>
@ -3236,7 +3240,7 @@
if (cookieDetails.length === 0) {
tbody.innerHTML = `
<tr>
<td colspan="6" class="text-center py-4 text-muted empty-state">
<td colspan="7" class="text-center py-4 text-muted empty-state">
<i class="bi bi-inbox fs-1 d-block mb-3"></i>
<h5>暂无账号</h5>
<p class="mb-0">请添加新的闲鱼账号开始使用</p>
@ -3271,16 +3275,28 @@
defaultReply = await defaultReplyResponse.json();
}
// 获取AI回复设置
const aiReplyResponse = await fetch(`${apiBase}/ai-reply-settings/${cookie.id}`, {
headers: { 'Authorization': `Bearer ${authToken}` }
});
let aiReply = { ai_enabled: false, model_name: 'qwen-plus' };
if (aiReplyResponse.ok) {
aiReply = await aiReplyResponse.json();
}
return {
...cookie,
keywordCount: keywordCount,
defaultReply: defaultReply
defaultReply: defaultReply,
aiReply: aiReply
};
} catch (error) {
return {
...cookie,
keywordCount: 0,
defaultReply: { enabled: false, reply_content: '' }
defaultReply: { enabled: false, reply_content: '' },
aiReply: { ai_enabled: false, model_name: 'qwen-plus' }
};
}
})
@ -3299,6 +3315,11 @@
'<span class="badge bg-success">启用</span>' :
'<span class="badge bg-secondary">禁用</span>';
// AI回复状态标签
const aiReplyBadge = cookie.aiReply.ai_enabled ?
'<span class="badge bg-primary">AI启用</span>' :
'<span class="badge bg-secondary">AI禁用</span>';
tr.innerHTML = `
<td class="align-middle">
<div class="cookie-id">
@ -3321,15 +3342,17 @@
<input type="checkbox" ${isEnabled ? 'checked' : ''} onchange="toggleAccountStatus('${cookie.id}', this.checked)">
<span class="status-slider"></span>
</label>
<span class="status-badge ${isEnabled ? 'enabled' : 'disabled'}">
<span class="status-badge ${isEnabled ? 'enabled' : 'disabled'}" title="${isEnabled ? '账号已启用' : '账号已禁用'}">
<i class="bi bi-${isEnabled ? 'check-circle-fill' : 'x-circle-fill'}"></i>
${isEnabled ? '启用' : '禁用'}
</span>
</div>
</td>
<td class="align-middle">
${defaultReplyBadge}
</td>
<td class="align-middle">
${aiReplyBadge}
</td>
<td class="align-middle">
<div class="btn-group" role="group">
<button class="btn btn-sm btn-outline-primary" onclick="editCookieInline('${cookie.id}', '${cookie.value}')" title="修改Cookie" ${!isEnabled ? 'disabled' : ''}>
@ -3338,6 +3361,9 @@
<button class="btn btn-sm btn-outline-success" onclick="goToAutoReply('${cookie.id}')" title="${isEnabled ? '设置自动回复' : '配置关键词 (账号已禁用)'}">
<i class="bi bi-arrow-right-circle"></i>
</button>
<button class="btn btn-sm btn-outline-warning" onclick="configAIReply('${cookie.id}')" title="配置AI回复" ${!isEnabled ? 'disabled' : ''}>
<i class="bi bi-robot"></i>
</button>
<button class="btn btn-sm btn-outline-info" onclick="copyCookie('${cookie.id}', '${cookie.value}')" title="复制Cookie">
<i class="bi bi-clipboard"></i>
</button>
@ -3618,9 +3644,9 @@
// 更新状态徽章
statusBadge.className = `status-badge ${enabled ? 'enabled' : 'disabled'}`;
statusBadge.title = enabled ? '账号已启用' : '账号已禁用';
statusBadge.innerHTML = `
<i class="bi bi-${enabled ? 'check-circle-fill' : 'x-circle-fill'}"></i>
${enabled ? '启用' : '禁用'}
`;
// 更新按钮状态只禁用编辑Cookie按钮其他按钮保持可用
@ -4009,6 +4035,177 @@
showToast('测试功能开发中...', 'info');
}
// ==================== AI回复配置相关函数 ====================
// 配置AI回复
async function configAIReply(accountId) {
try {
// 获取当前AI回复设置
const settings = await fetchJSON(`${apiBase}/ai-reply-settings/${accountId}`);
// 填充表单
document.getElementById('aiConfigAccountId').value = accountId;
document.getElementById('aiConfigAccountIdDisplay').value = accountId;
document.getElementById('aiReplyEnabled').checked = settings.ai_enabled;
document.getElementById('aiModelName').value = settings.model_name;
document.getElementById('aiBaseUrl').value = settings.base_url;
document.getElementById('aiApiKey').value = settings.api_key;
document.getElementById('maxDiscountPercent').value = settings.max_discount_percent;
document.getElementById('maxDiscountAmount').value = settings.max_discount_amount;
document.getElementById('maxBargainRounds').value = settings.max_bargain_rounds;
document.getElementById('customPrompts').value = settings.custom_prompts;
// 切换设置显示状态
toggleAIReplySettings();
// 显示模态框
const modal = new bootstrap.Modal(document.getElementById('aiReplyConfigModal'));
modal.show();
} catch (error) {
console.error('获取AI回复设置失败:', error);
showToast('获取AI回复设置失败', 'danger');
}
}
// 切换AI回复设置显示
function toggleAIReplySettings() {
const enabled = document.getElementById('aiReplyEnabled').checked;
const settingsDiv = document.getElementById('aiReplySettings');
const bargainSettings = document.getElementById('bargainSettings');
const promptSettings = document.getElementById('promptSettings');
const testArea = document.getElementById('testArea');
if (enabled) {
settingsDiv.style.display = 'block';
bargainSettings.style.display = 'block';
promptSettings.style.display = 'block';
testArea.style.display = 'block';
} else {
settingsDiv.style.display = 'none';
bargainSettings.style.display = 'none';
promptSettings.style.display = 'none';
testArea.style.display = 'none';
}
}
// 保存AI回复配置
async function saveAIReplyConfig() {
try {
const accountId = document.getElementById('aiConfigAccountId').value;
const enabled = document.getElementById('aiReplyEnabled').checked;
// 如果启用AI回复验证必填字段
if (enabled) {
const apiKey = document.getElementById('aiApiKey').value.trim();
if (!apiKey) {
showToast('请输入API密钥', 'warning');
return;
}
// 验证自定义提示词格式
const customPrompts = document.getElementById('customPrompts').value.trim();
if (customPrompts) {
try {
JSON.parse(customPrompts);
} catch (e) {
showToast('自定义提示词格式错误请检查JSON格式', 'warning');
return;
}
}
}
// 构建设置对象
const settings = {
ai_enabled: enabled,
model_name: document.getElementById('aiModelName').value,
api_key: document.getElementById('aiApiKey').value,
base_url: document.getElementById('aiBaseUrl').value,
max_discount_percent: parseInt(document.getElementById('maxDiscountPercent').value),
max_discount_amount: parseInt(document.getElementById('maxDiscountAmount').value),
max_bargain_rounds: parseInt(document.getElementById('maxBargainRounds').value),
custom_prompts: document.getElementById('customPrompts').value
};
// 保存设置
const response = await fetch(`${apiBase}/ai-reply-settings/${accountId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${authToken}`
},
body: JSON.stringify(settings)
});
if (response.ok) {
showToast('AI回复配置保存成功', 'success');
bootstrap.Modal.getInstance(document.getElementById('aiReplyConfigModal')).hide();
loadCookies(); // 刷新账号列表以更新AI回复状态显示
} else {
const error = await response.text();
showToast(`保存失败: ${error}`, 'danger');
}
} catch (error) {
console.error('保存AI回复配置失败:', error);
showToast('保存AI回复配置失败', 'danger');
}
}
// 测试AI回复
async function testAIReply() {
try {
const accountId = document.getElementById('aiConfigAccountId').value;
const testMessage = document.getElementById('testMessage').value.trim();
const testItemPrice = document.getElementById('testItemPrice').value;
if (!testMessage) {
showToast('请输入测试消息', 'warning');
return;
}
// 构建测试数据
const testData = {
message: testMessage,
item_title: '测试商品',
item_price: parseFloat(testItemPrice) || 100,
item_desc: '这是一个用于测试AI回复功能的商品'
};
// 显示加载状态
const testResult = document.getElementById('testResult');
const testReplyContent = document.getElementById('testReplyContent');
testResult.style.display = 'block';
testReplyContent.innerHTML = '<i class="bi bi-hourglass-split"></i> 正在生成AI回复...';
// 调用测试API
const response = await fetch(`${apiBase}/ai-reply-test/${accountId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${authToken}`
},
body: JSON.stringify(testData)
});
if (response.ok) {
const result = await response.json();
testReplyContent.innerHTML = result.reply;
showToast('AI回复测试成功', 'success');
} else {
const error = await response.text();
testReplyContent.innerHTML = `<span class="text-danger">测试失败: ${error}</span>`;
showToast(`测试失败: ${error}`, 'danger');
}
} catch (error) {
console.error('测试AI回复失败:', error);
const testReplyContent = document.getElementById('testReplyContent');
testReplyContent.innerHTML = `<span class="text-danger">测试失败: ${error.message}</span>`;
showToast('测试AI回复失败', 'danger');
}
}
// 监听默认回复启用状态变化
@ -6364,5 +6561,163 @@
</script>
<!-- AI回复配置模态框 -->
<div class="modal fade" id="aiReplyConfigModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="bi bi-robot me-2"></i>AI回复配置
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="aiReplyConfigForm">
<input type="hidden" id="aiConfigAccountId">
<!-- 基本设置 -->
<div class="card mb-3">
<div class="card-header">
<h6 class="mb-0"><i class="bi bi-gear me-2"></i>基本设置</h6>
</div>
<div class="card-body">
<div class="row mb-3">
<div class="col-md-6">
<label class="form-label">账号ID</label>
<input type="text" class="form-control" id="aiConfigAccountIdDisplay" readonly>
</div>
<div class="col-md-6">
<div class="form-check form-switch mt-4">
<input class="form-check-input" type="checkbox" id="aiReplyEnabled" onchange="toggleAIReplySettings()">
<label class="form-check-label" for="aiReplyEnabled">
<strong>启用AI回复</strong>
</label>
<small class="form-text text-muted d-block">启用后将自动禁用关键词匹配和默认回复</small>
</div>
</div>
</div>
<div id="aiReplySettings" style="display: none;">
<div class="row mb-3">
<div class="col-md-6">
<label for="aiModelName" class="form-label">AI模型</label>
<select class="form-select" id="aiModelName">
<option value="qwen-plus">通义千问Plus</option>
<option value="qwen-turbo">通义千问Turbo</option>
<option value="qwen-max">通义千问Max</option>
<option value="gpt-3.5-turbo">GPT-3.5 Turbo</option>
<option value="gpt-4">GPT-4</option>
</select>
</div>
<div class="col-md-6">
<label for="aiBaseUrl" class="form-label">API地址</label>
<input type="url" class="form-control" id="aiBaseUrl"
value="https://dashscope.aliyuncs.com/compatible-mode/v1"
placeholder="API Base URL">
</div>
</div>
<div class="mb-3">
<label for="aiApiKey" class="form-label">API密钥 <span class="text-danger">*</span></label>
<input type="password" class="form-control" id="aiApiKey"
placeholder="请输入API密钥" required>
<small class="form-text text-muted">
通义千问请使用DashScope API KeyGPT请使用OpenAI API Key
</small>
</div>
</div>
</div>
</div>
<!-- 议价设置 -->
<div class="card mb-3" id="bargainSettings" style="display: none;">
<div class="card-header">
<h6 class="mb-0"><i class="bi bi-currency-dollar me-2"></i>议价设置</h6>
</div>
<div class="card-body">
<div class="row mb-3">
<div class="col-md-4">
<label for="maxDiscountPercent" class="form-label">最大优惠百分比</label>
<div class="input-group">
<input type="number" class="form-control" id="maxDiscountPercent"
min="0" max="50" value="10">
<span class="input-group-text">%</span>
</div>
</div>
<div class="col-md-4">
<label for="maxDiscountAmount" class="form-label">最大优惠金额</label>
<div class="input-group">
<input type="number" class="form-control" id="maxDiscountAmount"
min="0" value="100">
<span class="input-group-text"></span>
</div>
</div>
<div class="col-md-4">
<label for="maxBargainRounds" class="form-label">最大议价轮数</label>
<input type="number" class="form-control" id="maxBargainRounds"
min="1" max="10" value="3">
</div>
</div>
</div>
</div>
<!-- 提示词设置 -->
<div class="card mb-3" id="promptSettings" style="display: none;">
<div class="card-header">
<h6 class="mb-0"><i class="bi bi-chat-quote me-2"></i>提示词设置</h6>
</div>
<div class="card-body">
<div class="mb-3">
<label class="form-label">自定义提示词 (JSON格式)</label>
<textarea class="form-control" id="customPrompts" rows="8"
placeholder='{"classify": "分类提示词", "price": "议价提示词", "tech": "技术提示词", "default": "默认提示词"}'></textarea>
<small class="form-text text-muted">
留空使用系统默认提示词。格式:{"classify": "...", "price": "...", "tech": "...", "default": "..."}
</small>
</div>
</div>
</div>
<!-- 测试区域 -->
<div class="card" id="testArea" style="display: none;">
<div class="card-header">
<h6 class="mb-0"><i class="bi bi-play-circle me-2"></i>功能测试</h6>
</div>
<div class="card-body">
<div class="row mb-3">
<div class="col-md-6">
<label for="testMessage" class="form-label">测试消息</label>
<input type="text" class="form-control" id="testMessage"
value="你好,这个商品能便宜点吗?" placeholder="输入测试消息">
</div>
<div class="col-md-6">
<label for="testItemPrice" class="form-label">商品价格</label>
<input type="number" class="form-control" id="testItemPrice"
value="100" placeholder="商品价格">
</div>
</div>
<button type="button" class="btn btn-outline-primary" onclick="testAIReply()">
<i class="bi bi-play me-1"></i>测试AI回复
</button>
<div id="testResult" class="mt-3" style="display: none;">
<div class="alert alert-info">
<strong>AI回复</strong>
<div id="testReplyContent"></div>
</div>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" onclick="saveAIReplyConfig()">
<i class="bi bi-check-lg me-1"></i>保存配置
</button>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,27 +0,0 @@
#!/usr/bin/env python3
"""
测试修复
"""
def test_imports():
print("🧪 测试导入修复")
try:
from file_log_collector import setup_file_logging, get_file_log_collector
print("✅ file_log_collector 导入成功")
# 测试初始化
collector = setup_file_logging()
print("✅ 文件日志收集器初始化成功")
# 生成测试日志
from loguru import logger
logger.info("测试日志修复")
print("✅ 所有导入和初始化都正常")
except Exception as e:
print(f"❌ 导入失败: {e}")
if __name__ == "__main__":
test_imports()

View File

@ -152,27 +152,133 @@ python Start.py
- 备份 `global_config.yml` 配置文件
- 备份自定义的关键词文件
## 🔧 高级功能
### AI回复配置
1. 在账号列表中点击"🤖 配置AI回复"
2. 开启AI回复功能
3. 配置API密钥和模型参数
4. 设置议价策略和优惠限制
5. 自定义提示词(可选)
### 自动发货设置
1. 进入"自动发货"页面
2. 添加发货规则和关键词匹配
3. 上传卡券文件或手动添加卡券
4. 配置发货模板和通知方式
### 商品管理
1. 进入"商品管理"页面
2. 查看自动收集的商品信息
3. 编辑商品详情和分类
4. 批量获取账号下所有商品
### 日志监控
1. 进入"日志管理"页面
2. 实时查看系统运行日志
3. 按级别和来源筛选日志
4. 查看系统统计信息
## 📊 数据管理
### 数据备份
1. 进入"系统设置"页面
2. 点击"导出备份"按钮
3. 下载备份文件到本地
4. 定期备份重要数据
### 数据恢复
1. 进入"系统设置"页面
2. 点击"导入备份"按钮
3. 选择备份文件上传
4. 确认恢复操作
### 数据清理
- 定期清理过期日志文件
- 删除无效的商品信息
- 清理过期的对话记录
## 📞 技术支持
### 测试系统
运行测试脚本检查系统状态:
```bash
python test_system.py
### 系统健康检查
访问健康检查端点
```
http://localhost:8080/health
```
### 重新创建配置
如果配置文件损坏,运行:
### 查看系统状态
```bash
python create_config.py
# 查看容器状态
docker-compose ps
# 查看系统资源使用
docker stats
# 查看实时日志
docker-compose logs -f
```
## 🎯 使用建议
### 常见问题解决
**问题1Cookie失效**
- 重新获取Cookie并更新
- 检查账号是否被限制
- 确认Cookie格式正确
**问题2消息接收异常**
- 检查网络连接
- 重启WebSocket连接
- 查看错误日志
**问题3AI回复失败**
- 检查API密钥是否正确
- 确认API服务可用
- 检查账户余额
## 🎯 最佳实践
### 安全建议
1. **定期更换密码**:修改默认管理员密码
2. **限制访问**仅允许信任的IP访问
3. **备份数据**:定期备份重要配置和数据
4. **监控日志**:定期查看系统日志
### 性能优化
1. **合理设置**:根据实际需求配置参数
2. **定期清理**:清理过期数据和日志
3. **监控资源**:关注系统资源使用情况
4. **优化配置**:根据使用情况调整配置
### 使用技巧
1. **Cookie获取**使用浏览器开发者工具获取完整Cookie
2. **关键词设置**:设置常用的咨询关键词和回复
3. **定期检查**:定期查看日志确保系统正常运行
4. **备份数据**:重要数据请及时备份
3. **AI配置**根据商品类型调整AI提示词
4. **发货规则**:设置精确的商品匹配规则
## 🔄 系统更新
### 更新步骤
1. 备份当前数据
2. 停止系统服务
3. 拉取最新代码
4. 重新构建镜像
5. 启动更新后的服务
### Docker更新
```bash
# 停止服务
docker-compose down
# 拉取最新代码
git pull
# 重新构建
./deploy.sh --update
# 检查状态
docker-compose ps
```
---
**注意**:本系统仅供学习交流使用,请遵守相关法律法规和平台规则。
**注意**:本系统仅供学习交流使用,请遵守相关法律法规和平台规则。使用前请仔细阅读相关文档,确保正确配置和使用。

View File

@ -194,6 +194,62 @@ Authorization: Bearer {token}
- 监控自动发货匹配情况
- 及时处理异常情况
## 🔧 故障排除
### 常见问题及解决方案
**问题1商品信息收集失败**
- 检查网络连接是否正常
- 确认Cookie是否有效
- 验证商品ID格式是否正确
- 查看详细错误日志
**问题2商品详情获取失败**
- 检查API服务是否可用
- 确认商品是否存在
- 验证请求参数是否正确
- 检查API配置
**问题3数据库操作失败**
- 检查数据库文件权限
- 确认磁盘空间是否充足
- 验证数据格式是否正确
- 查看数据库错误日志
### 性能优化建议
1. **定期清理**:清理无效的商品信息
2. **索引优化**:为常用查询字段建立索引
3. **批量操作**:使用批量操作提高效率
4. **缓存机制**:缓存常用的商品信息
## 📊 数据统计
### 商品统计信息
- **总商品数量**:系统中所有商品的总数
- **有效商品数**:包含完整信息的商品数量
- **账号分布**:各账号的商品数量分布
- **分类统计**:不同分类的商品数量
### 使用统计
- **收集成功率**:商品信息收集的成功率
- **API调用次数**商品详情API的调用统计
- **匹配成功率**:自动发货匹配的成功率
- **处理速度**:商品信息处理的平均速度
## 🚀 未来规划
### 即将推出的功能
1. **商品分析**:基于商品数据的深度分析
2. **价格监控**:监控商品价格变化趋势
3. **库存管理**:集成库存管理功能
4. **销量统计**:统计商品销售数据
### 长期发展方向
1. **智能推荐**:基于商品数据的智能推荐
2. **自动定价**:根据市场数据自动调整价格
3. **竞品分析**:分析同类商品的竞争情况
4. **数据挖掘**:深度挖掘商品数据价值
---
🎉 **商品管理功能让您的闲鱼自动发货更加智能和准确!**
🎉 **商品管理功能为您的闲鱼自动发货提供了强大的数据支持,让自动化运营更加智能和精准!通过持续优化和功能扩展,将为您带来更好的使用体验。**

View File

@ -280,17 +280,91 @@
## 🎯 使用建议
### 适用场景
- ✅ **开发调试**:实时查看程序运行状态
- ✅ **问题排查**:快速定位错误和异常
- ✅ **性能监控**:监控系统运行情况
- ✅ **用户支持**:协助用户解决问题
- ✅ **开发调试**:实时查看程序运行状态和调试信息
- ✅ **问题排查**:快速定位错误和异常,分析问题原因
- ✅ **性能监控**:监控系统运行情况和性能指标
- ✅ **用户支持**:协助用户解决问题,提供技术支持
- ✅ **运维监控**:生产环境的实时监控和告警
- ✅ **安全审计**:监控系统安全事件和异常行为
### 最佳实践
1. **开启自动刷新**:实时监控系统状态
2. **使用过滤器**:快速找到关注的日志
3. **查看统计信息**:了解系统整体状况
4. **定期清空**:避免内存占用过多
1. **开启自动刷新**:实时监控系统状态,及时发现问题
2. **合理使用过滤器**:根据需要过滤特定级别或来源的日志
3. **定期查看统计信息**:了解系统整体运行状况和趋势
4. **适时清空内存日志**:避免内存占用过多,保持系统性能
5. **结合文件日志**:重要日志同时查看文件日志进行备份
6. **设置告警规则**对ERROR级别日志设置告警通知
### 日志级别使用指南
- **DEBUG**:详细的调试信息,开发阶段使用
- **INFO**:一般信息,记录程序正常运行状态
- **WARNING**:警告信息,需要注意但不影响运行
- **ERROR**:错误信息,需要立即处理的问题
- **CRITICAL**:严重错误,可能导致程序崩溃
## 🔧 高级功能
### 日志导出
1. **实时导出**:将当前显示的日志导出为文件
2. **批量导出**:导出指定时间范围的日志
3. **格式选择**支持TXT、JSON、CSV等格式
4. **自动压缩**:大文件自动压缩处理
### 日志分析
1. **趋势分析**:分析日志数量和级别的时间趋势
2. **异常检测**:自动检测异常日志模式
3. **性能分析**:分析系统性能相关日志
4. **报表生成**:生成日志分析报表
### 告警配置
1. **级别告警**ERROR级别日志自动告警
2. **频率告警**:异常日志频率过高时告警
3. **关键词告警**:包含特定关键词的日志告警
4. **通知方式**支持邮件、短信、webhook等通知
## 🚨 故障排除
### 常见问题
**Q: 日志不更新?**
A: 检查以下项目:
- 自动刷新是否开启
- 网络连接是否正常
- 服务器是否正常运行
- 浏览器是否支持WebSocket
**Q: 日志显示不完整?**
A: 可能原因:
- 内存缓冲区已满,旧日志被清理
- 过滤器设置过于严格
- 日志级别设置不当
**Q: 性能影响?**
A: 优化建议:
- 适当调整刷新频率
- 使用过滤器减少显示数量
- 定期清空内存日志
- 关闭不必要的DEBUG日志
### 性能优化
1. **合理设置缓冲区大小**:根据系统内存调整
2. **优化刷新频率**:平衡实时性和性能
3. **使用过滤器**:减少不必要的日志传输
4. **定期清理**:避免内存泄漏
## 📊 监控指标
### 系统指标
- **日志生成速率**:每秒生成的日志数量
- **内存使用量**:日志缓冲区内存占用
- **处理延迟**:日志从生成到显示的延迟
- **错误率**ERROR级别日志的比例
### 业务指标
- **消息处理量**:处理的消息数量统计
- **API调用次数**各API接口的调用统计
- **用户活动**:用户操作和访问统计
- **系统健康度**:基于日志的系统健康评分
---
🎉 **实时日志管理功能已完成,提供了真正的实时日志查看、过滤和分析能力!**
🎉 **实时日志管理功能提供了完整的日志查看、分析和监控能力,是系统运维和问题排查的重要工具**

View File

@ -254,12 +254,92 @@ python test-item-info-delivery.py
## 💡 最佳实践
1. **规则设计**:关键字要具体明确,避免过于宽泛
2. **库存管理**:定期检查批量数据库存,及时补充
3. **监控告警**:设置发货失败告警,及时处理异常
4. **测试验证**:新规则上线前充分测试
5. **日志分析**:定期分析发货日志,优化匹配规则
### 规则设计原则
1. **关键字精确性**:关键字要具体明确,避免过于宽泛
2. **优先级设置**:重要商品设置更长的关键字,提高匹配优先级
3. **分类管理**:按商品类型分组管理发货规则
4. **定期更新**:根据商品变化及时更新匹配规则
### 库存管理策略
1. **实时监控**:定期检查批量数据库存状态
2. **预警机制**:设置库存低于阈值时的告警
3. **自动补充**:配置自动补充机制或定期手动补充
4. **分批管理**:将卡券分批次管理,避免一次性消耗完
### 质量控制措施
1. **测试验证**:新规则上线前在测试环境充分测试
2. **灰度发布**:新规则先在部分商品上试运行
3. **监控告警**:设置发货失败率告警,及时处理异常
4. **人工审核**:重要商品可设置人工审核环节
### 数据分析优化
1. **日志分析**:定期分析发货日志,识别问题模式
2. **成功率统计**:监控各规则的匹配成功率
3. **用户反馈**:收集买家反馈,优化发货内容
4. **性能监控**:监控发货响应时间,优化处理流程
## 🔧 故障排除
### 常见问题及解决方案
**问题1发货规则不匹配**
- 检查关键字是否正确
- 确认商品信息是否完整
- 验证匹配逻辑是否合理
- 查看详细的匹配日志
**问题2API接口调用失败**
- 检查API地址是否正确
- 验证请求参数和格式
- 确认网络连接状态
- 查看API服务状态
**问题3批量数据消耗过快**
- 检查匹配规则是否过于宽泛
- 确认是否有重复发货
- 调整匹配策略
- 增加库存补充频率
**问题4发货消息发送失败**
- 检查账号连接状态
- 验证消息格式是否正确
- 确认网络连接稳定
- 查看WebSocket连接日志
### 调试技巧
1. **开启详细日志**在配置中开启DEBUG级别日志
2. **单步测试**:使用测试功能验证单个规则
3. **模拟环境**:在测试环境模拟真实场景
4. **监控面板**:使用系统监控面板查看实时状态
## 📈 性能优化
### 系统性能优化
1. **缓存机制**缓存商品信息减少API调用
2. **异步处理**:使用异步处理提高并发能力
3. **连接池**:优化数据库连接池配置
4. **资源限制**:合理设置系统资源限制
### 业务流程优化
1. **规则优化**:优化匹配算法,提高匹配效率
2. **批量处理**:支持批量发货操作
3. **智能调度**:根据系统负载智能调度任务
4. **预处理**:预处理商品信息,提高匹配速度
## 🔐 安全考虑
### 数据安全
1. **敏感信息加密**:卡券内容加密存储
2. **访问控制**:严格的权限控制机制
3. **审计日志**:完整的操作审计日志
4. **备份恢复**:定期备份重要数据
### 业务安全
1. **防重复发货**:严格的重复发货检测
2. **异常监控**:实时监控异常发货行为
3. **人工干预**:支持紧急情况下的人工干预
4. **风险控制**:设置发货频率和数量限制
---
🎉 **自动发货功能让您的闲鱼店铺实现真正的自动化运营!**
🎉 **自动发货功能让您的闲鱼店铺实现真正的自动化运营!通过合理配置和优化,可以大大提高运营效率和用户体验。**

View File

@ -181,22 +181,120 @@ async def get_item_list_info(self, retry_count=0):
- 错误信息记录
- 便于问题排查
## 🚀 扩展可
## 🚀 高级功
### 1. 批量操作
- 支持多个账号批量获取
- 导出商品信息到文件
- 商品信息对比分析
- **多账号批量获取**:一次性获取所有账号的商品信息
- **定时自动获取**:设置定时任务自动更新商品信息
- **增量更新**:只获取新增或变更的商品信息
- **并发处理**:支持多账号并发获取,提高效率
### 2. 数据处理
- 商品信息入库存储
- 商品状态监控
- 价格变化追踪
### 2. 数据处理与分析
- **商品信息入库**:自动将获取的商品信息存储到数据库
- **商品状态监控**:监控商品上下架状态变化
- **价格变化追踪**:跟踪商品价格变化趋势
- **销量统计**:统计商品浏览量和销售数据
- **数据导出**支持导出为Excel、CSV等格式
### 3. 界面优化
- 商品信息表格显示
- 商品图片预览
- 筛选和搜索功能
- **商品信息表格**:以表格形式展示商品详细信息
- **商品图片预览**:显示商品主图和详情图
- **高级筛选**:按价格、分类、状态等条件筛选
- **搜索功能**:支持商品标题、描述的全文搜索
- **排序功能**:按时间、价格、浏览量等排序
### 4. 智能分析
- **商品分类统计**:自动分析商品分类分布
- **价格区间分析**:分析不同价格区间的商品数量
- **热门商品识别**:基于浏览量识别热门商品
- **库存预警**:监控商品库存状态,及时预警
## 📊 数据统计
### 获取统计信息
- **总商品数量**:账号下所有商品的总数
- **在售商品数**:当前在售状态的商品数量
- **已售出商品数**:已售出的商品数量
- **平均价格**:所有商品的平均售价
- **价格分布**:不同价格区间的商品分布
### 性能指标
- **获取速度**:每秒获取的商品数量
- **成功率**:获取成功的商品比例
- **错误率**:获取失败的商品比例
- **响应时间**API响应时间统计
## 🔧 故障排除
### 常见问题及解决方案
**问题1获取失败**
- 检查账号Cookie是否有效
- 确认网络连接是否正常
- 验证账号是否被限制
- 查看详细错误日志
**问题2获取速度慢**
- 检查网络连接质量
- 确认服务器负载情况
- 优化获取策略
- 考虑分批次获取
**问题3数据不完整**
- 检查API返回数据格式
- 确认商品状态是否正常
- 验证解析逻辑是否正确
- 查看控制台错误信息
**问题4Token频繁失效**
- 检查Cookie有效期
- 确认账号登录状态
- 优化Token刷新策略
- 考虑降低获取频率
### 调试技巧
1. **开启详细日志**:查看完整的获取过程
2. **单步测试**:先测试单个商品获取
3. **网络监控**:监控网络请求和响应
4. **数据验证**:验证获取数据的完整性
## 💡 使用建议
### 最佳实践
1. **合理频率**:避免过于频繁的获取操作
2. **错峰使用**:在网络较好的时段进行获取
3. **数据备份**:定期备份重要的商品数据
4. **监控告警**:设置获取失败的告警机制
### 性能优化
1. **缓存机制**:缓存已获取的商品信息
2. **增量更新**:只获取变更的商品信息
3. **并发控制**:合理控制并发获取数量
4. **资源管理**:及时释放不需要的资源
### 安全考虑
1. **权限控制**:限制获取功能的使用权限
2. **频率限制**:设置合理的获取频率限制
3. **数据保护**:保护获取的商品数据安全
4. **审计日志**:记录所有获取操作的审计日志
## 🔮 未来规划
### 即将推出的功能
1. **商品同步**:支持与其他平台的商品信息同步
2. **智能推荐**:基于商品数据的智能推荐算法
3. **自动定价**:根据市场数据自动调整商品价格
4. **竞品分析**:分析同类商品的价格和销量
### 长期发展方向
1. **大数据分析**:基于海量商品数据的深度分析
2. **机器学习**使用AI技术优化商品运营策略
3. **API开放**提供开放API供第三方系统集成
4. **移动端支持**:开发移动端应用,随时随地管理商品
---
🎉 **获取所有商品功能为商品管理提供了强大的数据获取能力,是商品分析和运营的重要工具!通过持续优化和功能扩展,将为用户提供更加完善的商品管理解决方案。**
---