diff --git a/.env.example b/.env.example index cbf2af2..b35365a 100644 --- a/.env.example +++ b/.env.example @@ -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 + # ================================ # 自动回复配置 # ================================ diff --git a/.gitignore b/.gitignore index e70e766..444c9a3 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,5 @@ __pypackages__/ venv/ ENV/ env.bak/ -venv.bak/ \ No newline at end of file +venv.bak/ +*.db \ No newline at end of file diff --git a/AI_REPLY_GUIDE.md b/AI_REPLY_GUIDE.md new file mode 100644 index 0000000..f700fd7 --- /dev/null +++ b/AI_REPLY_GUIDE.md @@ -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回复功能的使用方法。开始享受智能化的客服体验吧! diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..7656676 --- /dev/null +++ b/CHANGELOG.md @@ -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修复和问题解决 +- 📚 **文档更新**:文档和说明的更新 +- 🔒 **安全更新**:安全相关的更新和修复 + +### 兼容性说明 +- **向后兼容**:新版本保持与旧版本的兼容性 +- **配置迁移**:提供配置文件自动迁移功能 +- **数据迁移**:提供数据库自动升级功能 + +--- + +**注意**:建议在升级前备份重要数据,详细的升级指南请参考相关文档。 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..c897ef4 --- /dev/null +++ b/CONTRIBUTING.md @@ -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/) 规范: + +``` +[optional scope]: + +[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) 下发布。 + +--- + +**再次感谢您的贡献!** 🙏 + +每一个贡献都让这个项目变得更好,无论大小,我们都非常感激。让我们一起构建一个更好的闲鱼自动回复管理系统! diff --git a/LICENSE b/LICENSE index 4501f64..19a5768 100644 --- a/LICENSE +++ b/LICENSE @@ -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 diff --git a/README.md b/README.md index ce4260f..745de5a 100644 --- a/README.md +++ b/README.md @@ -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) +
-**✨ 基于闲鱼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文档) • [贡献指南](#-贡献指南) -## 🛠️ 快速开始 +
-### ⛳ 运行环境 -- 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) - 优秀的日志库 + +--- + +
+ +**如果这个项目对你有帮助,请给个 ⭐ 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) + +**让我们一起构建更好的闲鱼自动化工具!** 🚀 + +
+ +## 🔧 核心模块说明 + +### 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` +## � 更新日志 -#### 接口说明 -你需要实现这个接口,本项目会调用这个接口获取自动回复的内容并发送给客户 -不实现这个接口也没关系,系统会默认回复,你也可以配置默认回复的内容 -用于处理闲鱼消息的自动回复,支持对接大语言模型进行智能回复。 +查看 [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" -} -``` +## �🙏 致谢 -#### 响应格式 -```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 调用频率和成本控制 +
-## 📝 效果 +**如果这个项目对你有帮助,请给个 ⭐ 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) +
diff --git a/UI_IMPROVEMENTS.md b/UI_IMPROVEMENTS.md deleted file mode 100644 index 1ac59fc..0000000 --- a/UI_IMPROVEMENTS.md +++ /dev/null @@ -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不再隐藏**,便于查看和调试 -- ✅ **现代化设计**,视觉效果更佳 -- ✅ **功能增强**,操作更便利 -- ✅ **响应式优化**,支持各种设备 - -界面现在更加美观、实用和用户友好!🎨✨ diff --git a/XianyuAutoAsync.py b/XianyuAutoAsync.py index 56fcc48..916d2bf 100644 --- a/XianyuAutoAsync.py +++ b/XianyuAutoAsync.py @@ -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: diff --git a/ai_reply_engine.py b/ai_reply_engine.py new file mode 100644 index 0000000..bbf5f56 --- /dev/null +++ b/ai_reply_engine.py @@ -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() diff --git a/bargain_demo.py b/bargain_demo.py new file mode 100644 index 0000000..b2c0a36 --- /dev/null +++ b/bargain_demo.py @@ -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() diff --git a/db_manager.py b/db_manager.py index 24a05bc..2e39fbe 100644 --- a/db_manager.py +++ b/db_manager.py @@ -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'] diff --git a/deploy.bat b/deploy.bat deleted file mode 100644 index c10fd9d..0000000 --- a/deploy.bat +++ /dev/null @@ -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 %* diff --git a/docker-compose.yml b/docker-compose.yml index b9ffeb4..eb1bf49 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -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} diff --git a/docker-deploy.bat b/docker-deploy.bat deleted file mode 100644 index 671acb9..0000000 --- a/docker-deploy.bat +++ /dev/null @@ -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 %* diff --git a/docker-deploy.sh b/docker-deploy.sh deleted file mode 100644 index c79458a..0000000 --- a/docker-deploy.sh +++ /dev/null @@ -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 "$@" diff --git a/fix-db-permissions.bat b/fix-db-permissions.bat deleted file mode 100644 index fdcb358..0000000 --- a/fix-db-permissions.bat +++ /dev/null @@ -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 diff --git a/fix-db-permissions.sh b/fix-db-permissions.sh deleted file mode 100644 index e6ea4ff..0000000 --- a/fix-db-permissions.sh +++ /dev/null @@ -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" diff --git a/fix-docker-warnings.bat b/fix-docker-warnings.bat deleted file mode 100644 index 6810784..0000000 --- a/fix-docker-warnings.bat +++ /dev/null @@ -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 diff --git a/fix-docker-warnings.sh b/fix-docker-warnings.sh deleted file mode 100644 index 63d63e5..0000000 --- a/fix-docker-warnings.sh +++ /dev/null @@ -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" diff --git a/fix-websocket-issue.sh b/fix-websocket-issue.sh deleted file mode 100644 index d874a86..0000000 --- a/fix-websocket-issue.sh +++ /dev/null @@ -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. 检查网络连接和防火墙设置" diff --git a/global_config.yml b/global_config.yml index 467ad65..4ef32e4 100644 --- a/global_config.yml +++ b/global_config.yml @@ -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 diff --git a/quick-fix-permissions.bat b/quick-fix-permissions.bat deleted file mode 100644 index 762e0e5..0000000 --- a/quick-fix-permissions.bat +++ /dev/null @@ -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 diff --git a/quick-fix-permissions.sh b/quick-fix-permissions.sh deleted file mode 100644 index fbe55de..0000000 --- a/quick-fix-permissions.sh +++ /dev/null @@ -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 diff --git a/reply_server.py b/reply_server.py index 6840cd5..d5115e6 100644 --- a/reply_server.py +++ b/reply_server.py @@ -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") diff --git a/requirements.txt b/requirements.txt index f4a1a35..e381e03 100644 --- a/requirements.txt +++ b/requirements.txt @@ -26,4 +26,8 @@ psutil>=5.9.0 requests>=2.31.0 # 文件上传支持 -python-multipart>=0.0.6 \ No newline at end of file +python-multipart>=0.0.6 + +# AI回复相关 +openai>=1.65.5 +python-dotenv>=1.0.1 \ No newline at end of file diff --git a/static/index.html b/static/index.html index 63bf6db..61e9311 100644 --- a/static/index.html +++ b/static/index.html @@ -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 @@ 账号ID - Cookie值 - 关键词 - 状态 - 默认回复 - 操作 + Cookie值 + 关键词 + 状态 + 默认回复 + AI回复 + 操作 @@ -3236,7 +3240,7 @@ if (cookieDetails.length === 0) { tbody.innerHTML = ` - +
暂无账号

请添加新的闲鱼账号开始使用

@@ -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 @@ '启用' : '禁用'; + // AI回复状态标签 + const aiReplyBadge = cookie.aiReply.ai_enabled ? + 'AI启用' : + 'AI禁用'; + tr.innerHTML = ` ${defaultReplyBadge} + + ${aiReplyBadge} +
+ @@ -3618,9 +3644,9 @@ // 更新状态徽章 statusBadge.className = `status-badge ${enabled ? 'enabled' : 'disabled'}`; + statusBadge.title = enabled ? '账号已启用' : '账号已禁用'; statusBadge.innerHTML = ` - ${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 = ' 正在生成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 = `测试失败: ${error}`; + showToast(`测试失败: ${error}`, 'danger'); + } + + } catch (error) { + console.error('测试AI回复失败:', error); + const testReplyContent = document.getElementById('testReplyContent'); + testReplyContent.innerHTML = `测试失败: ${error.message}`; + showToast('测试AI回复失败', 'danger'); + } + } + // 监听默认回复启用状态变化 @@ -6364,5 +6561,163 @@ + + + \ No newline at end of file diff --git a/test_fix.py b/test_fix.py deleted file mode 100644 index c8360e4..0000000 --- a/test_fix.py +++ /dev/null @@ -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() diff --git a/使用说明.md b/使用说明.md index 008c929..e6e71c3 100644 --- a/使用说明.md +++ b/使用说明.md @@ -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 ``` -## 🎯 使用建议 +### 常见问题解决 +**问题1:Cookie失效** +- 重新获取Cookie并更新 +- 检查账号是否被限制 +- 确认Cookie格式正确 + +**问题2:消息接收异常** +- 检查网络连接 +- 重启WebSocket连接 +- 查看错误日志 + +**问题3:AI回复失败** +- 检查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 +``` --- -**注意**:本系统仅供学习交流使用,请遵守相关法律法规和平台规则。 +**注意**:本系统仅供学习交流使用,请遵守相关法律法规和平台规则。使用前请仔细阅读相关文档,确保正确配置和使用。 diff --git a/商品管理功能说明.md b/商品管理功能说明.md index 9ece907..8b2614c 100644 --- a/商品管理功能说明.md +++ b/商品管理功能说明.md @@ -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. **数据挖掘**:深度挖掘商品数据价值 + --- -🎉 **商品管理功能让您的闲鱼自动发货更加智能和准确!** +🎉 **商品管理功能为您的闲鱼自动发货提供了强大的数据支持,让自动化运营更加智能和精准!通过持续优化和功能扩展,将为您带来更好的使用体验。** diff --git a/日志管理功能说明.md b/日志管理功能说明.md index 5ed5981..185aba3 100644 --- a/日志管理功能说明.md +++ b/日志管理功能说明.md @@ -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接口的调用统计 +- **用户活动**:用户操作和访问统计 +- **系统健康度**:基于日志的系统健康评分 --- -🎉 **实时日志管理功能已完成,提供了真正的实时日志查看、过滤和分析能力!** +🎉 **实时日志管理功能提供了完整的日志查看、分析和监控能力,是系统运维和问题排查的重要工具!** diff --git a/自动发货功能说明.md b/自动发货功能说明.md index 059cdcb..f48c3ad 100644 --- a/自动发货功能说明.md +++ b/自动发货功能说明.md @@ -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:发货规则不匹配** +- 检查关键字是否正确 +- 确认商品信息是否完整 +- 验证匹配逻辑是否合理 +- 查看详细的匹配日志 + +**问题2:API接口调用失败** +- 检查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. **风险控制**:设置发货频率和数量限制 --- -🎉 **自动发货功能让您的闲鱼店铺实现真正的自动化运营!** +🎉 **自动发货功能让您的闲鱼店铺实现真正的自动化运营!通过合理配置和优化,可以大大提高运营效率和用户体验。** diff --git a/获取所有商品功能说明.md b/获取所有商品功能说明.md index ca70f87..ecf4dce 100644 --- a/获取所有商品功能说明.md +++ b/获取所有商品功能说明.md @@ -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返回数据格式 +- 确认商品状态是否正常 +- 验证解析逻辑是否正确 +- 查看控制台错误信息 + +**问题4:Token频繁失效** +- 检查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. **移动端支持**:开发移动端应用,随时随地管理商品 + +--- + +🎉 **获取所有商品功能为商品管理提供了强大的数据获取能力,是商品分析和运营的重要工具!通过持续优化和功能扩展,将为用户提供更加完善的商品管理解决方案。** ---