diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 9ed478b8..4ca3deb3 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,33 +1,44 @@ # Pull Request | PR 提交 -> **💡 提示 Tip:** 推荐 PR 标题格式 Recommended PR title format: `type(scope): description` -> 例如 Examples: `feat(trader): add new strategy` | `fix(api): resolve auth issue` -> 详情 Details: [PR Title Guide](./PR_TITLE_GUIDE.md) +> **📋 选择专用模板 | Choose Specialized Template** +> +> 我们现在提供了针对不同类型PR的专用模板,帮助你更快速地填写PR信息: +> We now offer specialized templates for different types of PRs to help you fill out the information faster: +> +> - 🔧 **[Backend PR Template](./PULL_REQUEST_TEMPLATE/backend.md)** | 后端PR模板 - For Go/API/Trading changes +> - 🎨 **[Frontend PR Template](./PULL_REQUEST_TEMPLATE/frontend.md)** | 前端PR模板 - For UI/UX changes +> - 📝 **[Documentation PR Template](./PULL_REQUEST_TEMPLATE/docs.md)** | 文档PR模板 - For documentation updates +> - 📦 **[General PR Template](./PULL_REQUEST_TEMPLATE/general.md)** | 通用PR模板 - For mixed or other changes +> +> **如何使用?| How to use?** +> - 创建PR时,在URL中添加 `?template=backend.md` 或其他模板名称 +> - When creating a PR, add `?template=backend.md` or other template name to the URL +> - 或者直接复制粘贴对应模板的内容 +> - Or simply copy and paste the content from the corresponding template + +--- + +> **💡 提示 Tip:** 推荐 PR 标题格式 `type(scope): description` +> 例如: `feat(trader): add new strategy` | `fix(api): resolve auth issue` --- ## 📝 Description | 描述 - - +**English:** | **中文:** -**English:** -**中文:** --- ## 🎯 Type of Change | 变更类型 - - - -- [ ] 🐛 Bug fix | 修复 Bug(不影响现有功能的修复) -- [ ] ✨ New feature | 新功能(不影响现有功能的新增) -- [ ] 💥 Breaking change | 破坏性变更(会导致现有功能无法正常工作的修复或功能) +- [ ] 🐛 Bug fix | 修复 Bug +- [ ] ✨ New feature | 新功能 +- [ ] 💥 Breaking change | 破坏性变更 - [ ] 📝 Documentation update | 文档更新 -- [ ] 🎨 Code style update | 代码样式更新(格式化、重命名等) -- [ ] ♻️ Refactoring | 重构(无功能变更) +- [ ] 🎨 Code style update | 代码样式更新 +- [ ] ♻️ Refactoring | 重构 - [ ] ⚡ Performance improvement | 性能优化 - [ ] ✅ Test update | 测试更新 - [ ] 🔧 Build/config change | 构建/配置变更 @@ -37,9 +48,6 @@ ## 🔗 Related Issues | 相关 Issue - - - - Closes # | 关闭 # - Related to # | 相关 # @@ -47,242 +55,50 @@ ## 📋 Changes Made | 具体变更 - - - -**English:** -- Change 1 -- Change 2 -- Change 3 - -**中文:** -- 变更 1 -- 变更 2 -- 变更 3 +**English:** | **中文:** +- +- --- ## 🧪 Testing | 测试 -### Manual Testing | 手动测试 - - - - - [ ] Tested locally | 本地测试通过 -- [ ] Tested on testnet | 测试网测试通过(交易所集成相关) -- [ ] Tested with different configurations | 测试了不同配置 +- [ ] Tests pass | 测试通过 - [ ] Verified no existing functionality broke | 确认没有破坏现有功能 -### Test Environment | 测试环境 - -- **OS | 操作系统:** [e.g. macOS, Ubuntu, Windows] -- **Go Version | Go 版本:** [e.g. 1.21.5] -- **Node Version | Node 版本:** [e.g. 18.x] (if applicable | 如适用) -- **Exchange | 交易所:** [if applicable | 如适用] - -### Test Results | 测试结果 - - - - -``` -Test output here | 测试输出 -``` - ---- - -## 📸 Screenshots / Demo | 截图/演示 - - - - - - - -**Before | 变更前:** - - -**After | 变更后:** - - --- ## ✅ Checklist | 检查清单 - - - ### Code Quality | 代码质量 - -- [ ] My code follows the project's code style | 我的代码遵循项目代码风格 ([Contributing Guide](../CONTRIBUTING.md)) -- [ ] I have performed a self-review of my code | 我已进行代码自查 -- [ ] I have commented my code, particularly in hard-to-understand areas | 我已添加代码注释,特别是难以理解的部分 -- [ ] My changes generate no new warnings or errors | 我的变更没有产生新的警告或错误 -- [ ] Code compiles successfully | 代码编译成功 (`go build` / `npm run build`) -- [ ] I have run `go fmt` (for Go code) | 我已运行 `go fmt`(Go 代码) -- [ ] I have run `npm run lint` (for frontend code) | 我已运行 `npm run lint`(前端代码) - -### Testing | 测试 - -- [ ] I have added tests that prove my fix is effective or that my feature works | 我已添加证明修复有效或功能正常的测试 -- [ ] New and existing unit tests pass locally | 新旧单元测试在本地通过 -- [ ] I have tested on testnet (for trading/exchange changes) | 我已在测试网测试(交易/交易所变更) -- [ ] Integration tests pass | 集成测试通过 +- [ ] Code follows project style | 代码遵循项目风格 +- [ ] Self-review completed | 已完成代码自查 +- [ ] Comments added for complex logic | 已添加必要注释 ### Documentation | 文档 - -- [ ] I have updated the documentation accordingly | 我已相应更新文档 -- [ ] I have updated the README if needed | 我已更新 README(如需要) -- [ ] I have added inline code comments where necessary | 我已在必要处添加代码注释 -- [ ] I have updated type definitions (for TypeScript changes) | 我已更新类型定义(TypeScript 变更) -- [ ] I have updated API documentation (if applicable) | 我已更新 API 文档(如适用) +- [ ] Updated relevant documentation | 已更新相关文档 ### Git - -- [ ] My commits follow the conventional commits format | 我的提交遵循 Conventional Commits 格式 (`feat:`, `fix:`, etc.) -- [ ] I have rebased my branch on the latest `dev` branch | 我已将分支 rebase 到最新的 `dev` 分支 -- [ ] There are no merge conflicts | 没有合并冲突 -- [ ] Commit messages are clear and descriptive | 提交信息清晰明确 - ---- - -## 🔒 Security Considerations | 安全考虑 - - - - -- [ ] No API keys or secrets are hardcoded | 没有硬编码 API 密钥或密钥 -- [ ] User inputs are properly validated | 用户输入已正确验证 -- [ ] No SQL injection vulnerabilities introduced | 未引入 SQL 注入漏洞 -- [ ] No XSS vulnerabilities introduced | 未引入 XSS 漏洞 -- [ ] Authentication/authorization properly handled | 认证/授权已正确处理 -- [ ] Sensitive data is encrypted | 敏感数据已加密 -- [ ] N/A (not security-related) | 不适用(非安全相关) - ---- - -## ⚡ Performance Impact | 性能影响 - - - - -- [ ] No significant performance impact | 无显著性能影响 -- [ ] Performance improved | 性能提升 -- [ ] Performance may be impacted (explain below) | 性能可能受影响(请在下方说明) - - - - -**English:** - -**中文:** - ---- - -## 🌐 Internationalization | 国际化 - - - - -- [ ] All user-facing text supports i18n | 所有面向用户的文本支持国际化 -- [ ] Both English and Chinese versions provided | 提供了中英文版本 -- [ ] N/A | 不适用 +- [ ] Commits follow conventional format | 提交遵循 Conventional Commits 格式 +- [ ] Rebased on latest `dev` branch | 已 rebase 到最新 `dev` 分支 +- [ ] No merge conflicts | 无合并冲突 --- ## 📚 Additional Notes | 补充说明 - - +**English:** | **中文:** -**English:** - -**中文:** --- -## 💰 For Bounty Claims | 赏金申请 +**By submitting this PR, I confirm | 提交此 PR,我确认:** - - - -- [ ] This PR is for bounty issue # | 此 PR 用于赏金 issue # -- [ ] All acceptance criteria from the bounty issue are met | 满足赏金 issue 的所有验收标准 -- [ ] I have included a demo video/screenshots | 我已包含演示视频/截图 -- [ ] I am ready for payment upon merge | 我准备好在合并后接收付款 - -**Payment Details | 付款详情:** +- [ ] I have read the [Contributing Guidelines](../CONTRIBUTING.md) | 已阅读贡献指南 +- [ ] I agree to the [Code of Conduct](../CODE_OF_CONDUCT.md) | 同意行为准则 +- [ ] My contribution is licensed under AGPL-3.0 | 贡献遵循 AGPL-3.0 许可证 --- -## 🙏 Reviewer Notes | 审查者注意事项 - - - - -**English:** - -**中文:** - ---- - -## 📋 PR Size Estimate | PR 大小估计 - - - - -- [ ] 🟢 Small (< 100 lines) | 小(< 100 行) -- [ ] 🟡 Medium (100-500 lines) | 中(100-500 行) -- [ ] 🔴 Large (> 500 lines) | 大(> 500 行) - - - - - - - ---- - -## 🎯 Review Focus Areas | 审查重点 - - - - -Please pay special attention to: -请特别注意: - -- [ ] Logic changes | 逻辑变更 -- [ ] Security implications | 安全影响 -- [ ] Performance optimization | 性能优化 -- [ ] API changes | API 变更 -- [ ] Database schema changes | 数据库架构变更 -- [ ] UI/UX changes | UI/UX 变更 - ---- - -**By submitting this PR, I confirm that:** -**提交此 PR,我确认:** - -- [ ] I have read the [Contributing Guidelines](../CONTRIBUTING.md) | 我已阅读[贡献指南](../CONTRIBUTING.md) -- [ ] I agree to the [Code of Conduct](../CODE_OF_CONDUCT.md) | 我同意[行为准则](../CODE_OF_CONDUCT.md) -- [ ] My contribution is licensed under the AGPL-3.0 License | 我的贡献遵循 AGPL-3.0 许可证 -- [ ] I understand this is a voluntary contribution | 我理解这是自愿贡献 -- [ ] I have the right to submit this code | 我有权提交此代码 - ---- - - +🌟 **Thank you for your contribution! | 感谢你的贡献!** diff --git a/.github/PULL_REQUEST_TEMPLATE/README.md b/.github/PULL_REQUEST_TEMPLATE/README.md new file mode 100644 index 00000000..f0478ba7 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/README.md @@ -0,0 +1,213 @@ +# PR Templates | PR 模板 + +## 📋 模板概述 | Template Overview + +我们提供了4种针对不同类型PR的专用模板,帮助贡献者快速填写PR信息: +We offer 4 specialized templates for different types of PRs to help contributors quickly fill out PR information: + +### 1. 🔧 Backend Template | 后端模板 +**文件:** `backend.md` + +**适用于 | Use for:** +- Go代码变更 | Go code changes +- API端点开发 | API endpoint development +- 交易逻辑实现 | Trading logic implementation +- 后端性能优化 | Backend performance optimization +- 数据库相关改动 | Database-related changes + +**包含 | Includes:** +- Go测试环境配置 | Go test environment +- 安全考虑检查 | Security considerations +- 性能影响评估 | Performance impact assessment +- `go fmt` 和 `go build` 检查 | `go fmt` and `go build` checks + +### 2. 🎨 Frontend Template | 前端模板 +**文件:** `frontend.md` + +**适用于 | Use for:** +- UI/UX变更 | UI/UX changes +- React/Vue组件开发 | React/Vue component development +- 前端样式更新 | Frontend styling updates +- 浏览器兼容性修复 | Browser compatibility fixes +- 前端性能优化 | Frontend performance optimization + +**包含 | Includes:** +- 截图/演示要求 | Screenshots/demo requirements +- 浏览器测试清单 | Browser testing checklist +- 国际化检查 | Internationalization checks +- 响应式设计验证 | Responsive design verification +- `npm run lint` 和 `npm run build` 检查 | Linting and build checks + +### 3. 📝 Documentation Template | 文档模板 +**文件:** `docs.md` + +**适用于 | Use for:** +- README更新 | README updates +- API文档编写 | API documentation +- 教程和指南 | Tutorials and guides +- 代码注释改进 | Code comment improvements +- 翻译工作 | Translation work + +**包含 | Includes:** +- 文档类型分类 | Documentation type classification +- 内容质量检查 | Content quality checks +- 双语要求(中英文)| Bilingual requirements (EN/CN) +- 链接有效性验证 | Link validity verification + +### 4. 📦 General Template | 通用模板 +**文件:** `general.md` + +**适用于 | Use for:** +- 混合类型变更 | Mixed-type changes +- 跨多个领域的PR | Cross-domain PRs +- 构建配置变更 | Build configuration changes +- 依赖更新 | Dependency updates +- 不确定使用哪个模板时 | When unsure which template to use + +## 🤖 自动模板建议 | Automatic Template Suggestion + +我们的GitHub Action会自动分析你的PR并建议最合适的模板: +Our GitHub Action automatically analyzes your PR and suggests the most suitable template: + +### 工作原理 | How it works: + +1. **文件分析 | File Analysis** + - 检测PR中所有变更的文件类型 + - Detects all changed file types in the PR + +2. **智能判断 | Smart Detection** + - 如果 >50% 是 `.go` 文件 → 建议**后端模板** + - If >50% are `.go` files → Suggests **Backend template** + - 如果 >50% 是 `.js/.ts/.tsx/.vue` 文件 → 建议**前端模板** + - If >50% are `.js/.ts/.tsx/.vue` files → Suggests **Frontend template** + - 如果 >70% 是 `.md` 文件 → 建议**文档模板** + - If >70% are `.md` files → Suggests **Documentation template** + +3. **自动评论 | Auto-comment** + - 如果检测到你使用了默认模板,但应该用专用模板 + - If it detects you're using the default template but should use a specialized one + - 会自动添加友好的评论建议 + - It will automatically add a friendly comment suggestion + +4. **自动标签 | Auto-labeling** + - 自动添加对应的标签:`backend`、`frontend`、`documentation` + - Automatically adds corresponding labels: `backend`, `frontend`, `documentation` + +## 📖 使用方法 | How to Use + +### 方法1: URL参数(推荐) | Method 1: URL Parameter (Recommended) + +创建PR时,在URL末尾添加模板参数: +When creating a PR, add the template parameter to the URL: + +``` +https://github.com/YOUR_ORG/nofx/compare/dev...YOUR_BRANCH?template=backend.md +``` + +替换 `backend.md` 为: +Replace `backend.md` with: +- `backend.md` - 后端模板 | Backend template +- `frontend.md` - 前端模板 | Frontend template +- `docs.md` - 文档模板 | Documentation template +- `general.md` - 通用模板 | General template + +### 方法2: 手动选择 | Method 2: Manual Selection + +1. 创建PR时,默认模板会显示 + When creating a PR, the default template will be shown + +2. 根据顶部的指引链接,点击查看对应的模板 + Follow the guidance links at the top to view the corresponding template + +3. 复制模板内容到PR描述中 + Copy the template content into the PR description + +### 方法3: 跟随自动建议 | Method 3: Follow Auto-suggestion + +1. 使用任何模板创建PR + Create a PR with any template + +2. GitHub Action会自动分析并评论建议 + GitHub Action will automatically analyze and comment with a suggestion + +3. 根据建议更新PR描述 + Update the PR description based on the suggestion + +## 🎯 最佳实践 | Best Practices + +1. **提前选择 | Choose in Advance** + - 在创建PR前确定变更类型 + - Determine the change type before creating the PR + +2. **完整填写 | Complete Filling** + - 不要跳过必填项(标记为 required) + - Don't skip required items + +3. **保持简洁 | Keep it Concise** + - 描述清晰但简洁 + - Keep descriptions clear but concise + +4. **添加截图 | Add Screenshots** + - 对于UI变更,务必添加截图 + - For UI changes, always add screenshots + +5. **测试证明 | Test Evidence** + - 提供测试通过的证据 + - Provide evidence that tests pass + +## 🔧 自定义 | Customization + +如果需要修改模板或自动检测逻辑: +If you need to modify templates or auto-detection logic: + +1. **修改模板** | **Modify Templates** + - 编辑 `.github/PULL_REQUEST_TEMPLATE/*.md` 文件 + - Edit `.github/PULL_REQUEST_TEMPLATE/*.md` files + +2. **调整检测阈值** | **Adjust Detection Threshold** + - 编辑 `.github/workflows/pr-template-suggester.yml` + - Edit `.github/workflows/pr-template-suggester.yml` + - 修改文件类型占比阈值(当前:50%后端,50%前端,70%文档) + - Modify file type percentage thresholds (current: 50% backend, 50% frontend, 70% docs) + +3. **添加新模板** | **Add New Template** + - 在 `PULL_REQUEST_TEMPLATE/` 目录创建新的 `.md` 文件 + - Create a new `.md` file in the `PULL_REQUEST_TEMPLATE/` directory + - 更新工作流以支持新的文件类型检测 + - Update the workflow to support new file type detection + +## ❓ FAQ + +**Q: 我的PR既有前端又有后端代码,用哪个模板?** +**Q: My PR has both frontend and backend code, which template should I use?** + +A: 使用**通用模板**(`general.md`),或选择主要变更类型的模板。 +A: Use the **General template** (`general.md`), or choose the template for the primary change type. + +--- + +**Q: 自动建议的模板不合适怎么办?** +**Q: What if the automatically suggested template is not suitable?** + +A: 你可以忽略建议,继续使用当前模板。自动建议仅供参考。 +A: You can ignore the suggestion and continue using the current template. Auto-suggestions are for reference only. + +--- + +**Q: 可以不使用任何模板吗?** +**Q: Can I not use any template?** + +A: 不推荐。模板帮助确保PR包含必要信息,加快审查速度。 +A: Not recommended. Templates help ensure PRs contain necessary information and speed up reviews. + +--- + +**Q: 如何禁用自动模板建议?** +**Q: How to disable automatic template suggestions?** + +A: 删除或禁用 `.github/workflows/pr-template-suggester.yml` 文件。 +A: Delete or disable the `.github/workflows/pr-template-suggester.yml` file. + +--- + +🌟 **感谢使用我们的PR模板系统!| Thank you for using our PR template system!** diff --git a/.github/PULL_REQUEST_TEMPLATE/backend.md b/.github/PULL_REQUEST_TEMPLATE/backend.md new file mode 100644 index 00000000..dfc354c3 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/backend.md @@ -0,0 +1,121 @@ +# Pull Request - Backend | 后端 PR + +> **💡 提示 Tip:** 推荐 PR 标题格式 `type(scope): description` +> 例如: `feat(trader): add new strategy` | `fix(api): resolve auth issue` + +--- + +## 📝 Description | 描述 + +**English:** | **中文:** + + + +--- + +## 🎯 Type of Change | 变更类型 + +- [ ] 🐛 Bug fix | 修复 Bug +- [ ] ✨ New feature | 新功能 +- [ ] 💥 Breaking change | 破坏性变更 +- [ ] ♻️ Refactoring | 重构 +- [ ] ⚡ Performance improvement | 性能优化 +- [ ] 🔒 Security fix | 安全修复 +- [ ] 🔧 Build/config change | 构建/配置变更 + +--- + +## 🔗 Related Issues | 相关 Issue + +- Closes # | 关闭 # +- Related to # | 相关 # + +--- + +## 📋 Changes Made | 具体变更 + +**English:** | **中文:** +- +- + +--- + +## 🧪 Testing | 测试 + +### Test Environment | 测试环境 +- **OS | 操作系统:** +- **Go Version | Go 版本:** +- **Exchange | 交易所:** [if applicable | 如适用] + +### Manual Testing | 手动测试 +- [ ] Tested locally | 本地测试通过 +- [ ] Tested on testnet | 测试网测试通过(交易所集成相关) +- [ ] Unit tests pass | 单元测试通过 +- [ ] Verified no existing functionality broke | 确认没有破坏现有功能 + +### Test Results | 测试结果 +``` +Test output here | 测试输出 +``` + +--- + +## 🔒 Security Considerations | 安全考虑 + +- [ ] No API keys or secrets hardcoded | 没有硬编码 API 密钥 +- [ ] User inputs properly validated | 用户输入已正确验证 +- [ ] No SQL injection vulnerabilities | 无 SQL 注入漏洞 +- [ ] Authentication/authorization properly handled | 认证/授权正确处理 +- [ ] Sensitive data is encrypted | 敏感数据已加密 +- [ ] N/A (not security-related) | 不适用 + +--- + +## ⚡ Performance Impact | 性能影响 + +- [ ] No significant performance impact | 无显著性能影响 +- [ ] Performance improved | 性能提升 +- [ ] Performance may be impacted (explain below) | 性能可能受影响 + +**If impacted, explain | 如果受影响,请说明:** + + +--- + +## ✅ Checklist | 检查清单 + +### Code Quality | 代码质量 +- [ ] Code follows project style | 代码遵循项目风格 +- [ ] Self-review completed | 已完成代码自查 +- [ ] Comments added for complex logic | 已添加必要注释 +- [ ] Code compiles successfully | 代码编译成功 (`go build`) +- [ ] Ran `go fmt` | 已运行 `go fmt` + +### Documentation | 文档 +- [ ] Updated relevant documentation | 已更新相关文档 +- [ ] Added inline comments where necessary | 已添加必要的代码注释 +- [ ] Updated API documentation (if applicable) | 已更新 API 文档 + +### Git +- [ ] Commits follow conventional format | 提交遵循 Conventional Commits 格式 +- [ ] Rebased on latest `dev` branch | 已 rebase 到最新 `dev` 分支 +- [ ] No merge conflicts | 无合并冲突 + +--- + +## 📚 Additional Notes | 补充说明 + +**English:** | **中文:** + + +--- + +**By submitting this PR, I confirm | 提交此 PR,我确认:** + +- [ ] I have read the [Contributing Guidelines](../../CONTRIBUTING.md) | 已阅读贡献指南 +- [ ] I agree to the [Code of Conduct](../../CODE_OF_CONDUCT.md) | 同意行为准则 +- [ ] My contribution is licensed under AGPL-3.0 | 贡献遵循 AGPL-3.0 许可证 + +--- + +🌟 **Thank you for your contribution! | 感谢你的贡献!** diff --git a/.github/PULL_REQUEST_TEMPLATE/docs.md b/.github/PULL_REQUEST_TEMPLATE/docs.md new file mode 100644 index 00000000..2ce9a90c --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/docs.md @@ -0,0 +1,97 @@ +# Pull Request - Documentation | 文档 PR + +> **💡 提示 Tip:** 推荐 PR 标题格式 `docs(scope): description` +> 例如: `docs(api): update trading endpoints` | `docs(readme): add setup guide` + +--- + +## 📝 Description | 描述 + +**English:** | **中文:** + + +--- + +## 📚 Type of Documentation | 文档类型 + +- [ ] 📖 README update | README 更新 +- [ ] 📋 API documentation | API 文档 +- [ ] 🎓 Tutorial/Guide | 教程/指南 +- [ ] 📝 Code comments | 代码注释 +- [ ] 🔧 Configuration docs | 配置文档 +- [ ] 🐛 Fix typo/error | 修复拼写/错误 +- [ ] 🌍 Translation | 翻译 + +--- + +## 🔗 Related Issues | 相关 Issue + +- Closes # | 关闭 # +- Related to # | 相关 # + +--- + +## 📋 Changes Made | 具体变更 + +**English:** | **中文:** +- +- + +--- + +## 📸 Screenshots (if applicable) | 截图(如适用) + + + + + +--- + +## 🌐 Internationalization | 国际化 + +- [ ] English version complete | 英文版本完整 +- [ ] Chinese version complete | 中文版本完整 +- [ ] Both versions are consistent | 两个版本内容一致 +- [ ] N/A (only one language needed) | 不适用(只需要一种语言) + +--- + +## ✅ Checklist | 检查清单 + +### Content Quality | 内容质量 +- [ ] Information is accurate and up-to-date | 信息准确且最新 +- [ ] Language is clear and concise | 语言清晰简洁 +- [ ] No spelling or grammar errors | 无拼写或语法错误 +- [ ] Links are valid and working | 链接有效且可用 +- [ ] Code examples are tested and working | 代码示例已测试且可用 +- [ ] Formatting is consistent | 格式一致 + +### Documentation Standards | 文档标准 +- [ ] Follows project documentation style | 遵循项目文档风格 +- [ ] Includes necessary examples | 包含必要的示例 +- [ ] Technical terms are explained | 技术术语已解释 +- [ ] Self-review completed | 已完成自查 + +### Git +- [ ] Commits follow conventional format | 提交遵循 Conventional Commits 格式 +- [ ] Rebased on latest `dev` branch | 已 rebase 到最新 `dev` 分支 +- [ ] No merge conflicts | 无合并冲突 + +--- + +## 📚 Additional Notes | 补充说明 + +**English:** | **中文:** + + +--- + +**By submitting this PR, I confirm | 提交此 PR,我确认:** + +- [ ] I have read the [Contributing Guidelines](../../CONTRIBUTING.md) | 已阅读贡献指南 +- [ ] I agree to the [Code of Conduct](../../CODE_OF_CONDUCT.md) | 同意行为准则 +- [ ] My contribution is licensed under AGPL-3.0 | 贡献遵循 AGPL-3.0 许可证 + +--- + +🌟 **Thank you for your contribution! | 感谢你的贡献!** diff --git a/.github/PULL_REQUEST_TEMPLATE/frontend.md b/.github/PULL_REQUEST_TEMPLATE/frontend.md new file mode 100644 index 00000000..b95a20d0 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/frontend.md @@ -0,0 +1,119 @@ +# Pull Request - Frontend | 前端 PR + +> **💡 提示 Tip:** 推荐 PR 标题格式 `type(scope): description` +> 例如: `feat(ui): add dark mode toggle` | `fix(form): resolve validation bug` + +--- + +## 📝 Description | 描述 + +**English:** | **中文:** + + +--- + +## 🎯 Type of Change | 变更类型 + +- [ ] 🐛 Bug fix | 修复 Bug +- [ ] ✨ New feature | 新功能 +- [ ] 💥 Breaking change | 破坏性变更 +- [ ] 🎨 Code style update | 代码样式更新 +- [ ] ♻️ Refactoring | 重构 +- [ ] ⚡ Performance improvement | 性能优化 + +--- + +## 🔗 Related Issues | 相关 Issue + +- Closes # | 关闭 # +- Related to # | 相关 # + +--- + +## 📋 Changes Made | 具体变更 + +**English:** | **中文:** +- +- + +--- + +## 📸 Screenshots / Demo | 截图/演示 + + + + +**Before | 变更前:** + + +**After | 变更后:** + + +--- + +## 🧪 Testing | 测试 + +### Test Environment | 测试环境 +- **OS | 操作系统:** +- **Node Version | Node 版本:** +- **Browser(s) | 浏览器:** + +### Manual Testing | 手动测试 +- [ ] Tested in development mode | 开发模式测试通过 +- [ ] Tested production build | 生产构建测试通过 +- [ ] Tested on multiple browsers | 多浏览器测试通过 +- [ ] Tested responsive design | 响应式设计测试通过 +- [ ] Verified no existing functionality broke | 确认没有破坏现有功能 + +--- + +## 🌐 Internationalization | 国际化 + +- [ ] All user-facing text supports i18n | 所有面向用户的文本支持国际化 +- [ ] Both English and Chinese versions provided | 提供了中英文版本 +- [ ] N/A | 不适用 + +--- + +## ✅ Checklist | 检查清单 + +### Code Quality | 代码质量 +- [ ] Code follows project style | 代码遵循项目风格 +- [ ] Self-review completed | 已完成代码自查 +- [ ] Comments added for complex logic | 已添加必要注释 +- [ ] Code builds successfully | 代码构建成功 (`npm run build`) +- [ ] Ran `npm run lint` | 已运行 `npm run lint` +- [ ] No console errors or warnings | 无控制台错误或警告 + +### Testing | 测试 +- [ ] Component tests added/updated | 已添加/更新组件测试 +- [ ] Tests pass locally | 测试在本地通过 + +### Documentation | 文档 +- [ ] Updated relevant documentation | 已更新相关文档 +- [ ] Updated type definitions (TypeScript) | 已更新类型定义 +- [ ] Added JSDoc comments where necessary | 已添加 JSDoc 注释 + +### Git +- [ ] Commits follow conventional format | 提交遵循 Conventional Commits 格式 +- [ ] Rebased on latest `dev` branch | 已 rebase 到最新 `dev` 分支 +- [ ] No merge conflicts | 无合并冲突 + +--- + +## 📚 Additional Notes | 补充说明 + +**English:** | **中文:** + + +--- + +**By submitting this PR, I confirm | 提交此 PR,我确认:** + +- [ ] I have read the [Contributing Guidelines](../../CONTRIBUTING.md) | 已阅读贡献指南 +- [ ] I agree to the [Code of Conduct](../../CODE_OF_CONDUCT.md) | 同意行为准则 +- [ ] My contribution is licensed under AGPL-3.0 | 贡献遵循 AGPL-3.0 许可证 + +--- + +🌟 **Thank you for your contribution! | 感谢你的贡献!** diff --git a/.github/PULL_REQUEST_TEMPLATE/general.md b/.github/PULL_REQUEST_TEMPLATE/general.md new file mode 100644 index 00000000..23773e4c --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/general.md @@ -0,0 +1,98 @@ +# Pull Request - General | 通用 PR + +> **💡 提示 Tip:** 推荐 PR 标题格式 `type(scope): description` +> 例如: `feat(trader): add new strategy` | `fix(api): resolve auth issue` | `docs(readme): update` + +--- + +## 📝 Description | 描述 + +**English:** | **中文:** + + +--- + +## 🎯 Type of Change | 变更类型 + +- [ ] 🐛 Bug fix | 修复 Bug +- [ ] ✨ New feature | 新功能 +- [ ] 💥 Breaking change | 破坏性变更 +- [ ] 📝 Documentation update | 文档更新 +- [ ] 🎨 Code style update | 代码样式更新 +- [ ] ♻️ Refactoring | 重构 +- [ ] ⚡ Performance improvement | 性能优化 +- [ ] ✅ Test update | 测试更新 +- [ ] 🔧 Build/config change | 构建/配置变更 +- [ ] 🔒 Security fix | 安全修复 + +--- + +## 🔗 Related Issues | 相关 Issue + +- Closes # | 关闭 # +- Related to # | 相关 # + +--- + +## 📋 Changes Made | 具体变更 + +**English:** | **中文:** +- +- + +--- + +## 🧪 Testing | 测试 + +- [ ] Tested locally | 本地测试通过 +- [ ] Tests pass | 测试通过 +- [ ] Verified no existing functionality broke | 确认没有破坏现有功能 + +**Test details | 测试详情:** + + +--- + +## ✅ Checklist | 检查清单 + +### Code Quality | 代码质量 +- [ ] Code follows project style | 代码遵循项目风格 +- [ ] Self-review completed | 已完成代码自查 +- [ ] Comments added for complex logic | 已添加必要注释 +- [ ] No new warnings or errors | 无新的警告或错误 + +### Documentation | 文档 +- [ ] Updated relevant documentation | 已更新相关文档 +- [ ] Added inline comments where necessary | 已添加必要的代码注释 + +### Git +- [ ] Commits follow conventional format | 提交遵循 Conventional Commits 格式 +- [ ] Rebased on latest `dev` branch | 已 rebase 到最新 `dev` 分支 +- [ ] No merge conflicts | 无合并冲突 + +--- + +## 🔒 Security (if applicable) | 安全(如适用) + +- [ ] No API keys or secrets hardcoded | 没有硬编码 API 密钥 +- [ ] User inputs properly validated | 用户输入已正确验证 +- [ ] N/A | 不适用 + +--- + +## 📚 Additional Notes | 补充说明 + +**English:** | **中文:** + + +--- + +**By submitting this PR, I confirm | 提交此 PR,我确认:** + +- [ ] I have read the [Contributing Guidelines](../../CONTRIBUTING.md) | 已阅读贡献指南 +- [ ] I agree to the [Code of Conduct](../../CODE_OF_CONDUCT.md) | 同意行为准则 +- [ ] My contribution is licensed under AGPL-3.0 | 贡献遵循 AGPL-3.0 许可证 + +--- + +🌟 **Thank you for your contribution! | 感谢你的贡献!** diff --git a/.github/workflows/pr-template-suggester.yml b/.github/workflows/pr-template-suggester.yml new file mode 100644 index 00000000..9e74a9e4 --- /dev/null +++ b/.github/workflows/pr-template-suggester.yml @@ -0,0 +1,189 @@ +name: PR Template Suggester + +on: + pull_request: + types: [opened, edited, synchronize] + +permissions: + pull-requests: write + contents: read + +jobs: + suggest-template: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Analyze PR files and auto-apply template + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { data: files } = await github.rest.pulls.listFiles({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.issue.number, + }); + + let goFiles = 0, jsFiles = 0, tsFiles = 0, mdFiles = 0, otherFiles = 0; + + for (const file of files) { + const filename = file.filename.toLowerCase(); + if (filename.endsWith('.go')) goFiles++; + else if (filename.endsWith('.js') || filename.endsWith('.jsx')) jsFiles++; + else if (filename.endsWith('.ts') || filename.endsWith('.tsx') || filename.endsWith('.vue')) tsFiles++; + else if (filename.endsWith('.md')) mdFiles++; + else otherFiles++; + } + + const totalFiles = goFiles + jsFiles + tsFiles + mdFiles + otherFiles; + if (totalFiles === 0) { console.log('No files changed'); return; } + + let suggestedTemplate = null, templateEmoji = '', templateLabel = ''; + + if (goFiles / totalFiles > 0.5) { + suggestedTemplate = 'backend'; templateEmoji = '🔧'; templateLabel = 'backend'; + } else if ((jsFiles + tsFiles) / totalFiles > 0.5) { + suggestedTemplate = 'frontend'; templateEmoji = '🎨'; templateLabel = 'frontend'; + } else if (mdFiles / totalFiles > 0.7) { + suggestedTemplate = 'docs'; templateEmoji = '📝'; templateLabel = 'documentation'; + } + + const { data: pr } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.issue.number, + }); + + const prBody = pr.body || ''; + const usesBackendTemplate = prBody.includes('Pull Request - Backend'); + const usesFrontendTemplate = prBody.includes('Pull Request - Frontend'); + const usesDocsTemplate = prBody.includes('Pull Request - Documentation'); + const usesGeneralTemplate = prBody.includes('Pull Request - General'); + const usingDefaultTemplate = !usesBackendTemplate && !usesFrontendTemplate && !usesDocsTemplate && !usesGeneralTemplate; + + if (templateLabel) { + try { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + labels: [templateLabel] + }); + console.log('Added label: ' + templateLabel); + } catch (error) { + console.log('Label might not exist, skipping...'); + } + } + + function isPRBodyEmpty(body) { + if (!body || body.trim().length < 100) return true; + const hasEmptyDescription = body.includes('**English:**') && body.match(/\*\*English:\*\*\s*\n\s*\n\s*\n/); + const hasEmptyChanges = body.includes('具体变更') && body.match(/\*\*中文:\*\*\s*\n\s*-\s*\n\s*-\s*\n/); + if (hasEmptyDescription || hasEmptyChanges) return true; + const descMatch = body.match(/\*\*English:\*\*[||]\s*\*\*中文:\*\*\s*\n\s*(.+)/); + if (!descMatch || descMatch[1].trim().length < 10) return true; + return false; + } + + if (suggestedTemplate && usingDefaultTemplate) { + const shouldAutoApply = isPRBodyEmpty(prBody); + const templatePath = '.github/PULL_REQUEST_TEMPLATE/' + suggestedTemplate + '.md'; + + if (shouldAutoApply) { + try { + const { data: templateFile } = await github.rest.repos.getContent({ + owner: context.repo.owner, + repo: context.repo.repo, + path: templatePath, + ref: context.payload.pull_request.head.ref + }); + + const templateContent = Buffer.from(templateFile.content, 'base64').toString('utf-8'); + + await github.rest.pulls.update({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.issue.number, + body: templateContent + }); + + console.log('Auto-applied ' + suggestedTemplate + ' template'); + + let fileStats = []; + if (goFiles > 0) fileStats.push('- 🔧 Go files: ' + goFiles); + if (jsFiles > 0) fileStats.push('- 🎨 JavaScript files: ' + jsFiles); + if (tsFiles > 0) fileStats.push('- 🎨 TypeScript files: ' + tsFiles); + if (mdFiles > 0) fileStats.push('- 📝 Markdown files: ' + mdFiles); + if (otherFiles > 0) fileStats.push('- 📦 Other files: ' + otherFiles); + const fileStatsText = fileStats.join('\n'); + + const notifyComment = '## ' + templateEmoji + ' 已自动应用专用模板 | Auto-Applied Template\n\n' + + '检测到您的PR主要包含 **' + suggestedTemplate + '** 相关的变更,系统已自动为您应用相应的模板。\n\n' + + 'Detected that your PR primarily contains **' + suggestedTemplate + '** changes. The appropriate template has been automatically applied.\n\n' + + '**文件统计 | File Statistics**\n' + fileStatsText + '\n\n' + + '**已应用模板 | Applied Template**\n`' + templatePath + '`\n\n' + + '✨ 您现在可以直接在PR描述中填写相关信息了!\n\n' + + '✨ You can now fill in the relevant information in the PR description!'; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: notifyComment + }); + + } catch (error) { + console.log('Failed to fetch or apply template: ' + error.message); + const templateUrl = 'https://raw.githubusercontent.com/' + context.repo.owner + '/' + context.repo.repo + '/dev/.github/PULL_REQUEST_TEMPLATE/' + suggestedTemplate + '.md'; + const fallbackComment = '## ' + templateEmoji + ' 建议使用专用模板 | Suggested Template\n\n' + + '您的PR主要包含 **' + suggestedTemplate + '** 相关的变更。\n\n' + + '**推荐模板 | Recommended Template:** `.github/PULL_REQUEST_TEMPLATE/' + suggestedTemplate + '.md`\n\n' + + '**如何使用 | How to use:** [点击查看模板内容](' + templateUrl + ')'; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: fallbackComment + }); + } + } else { + console.log('PR body has content, sending suggestion only'); + + let fileStats = []; + if (goFiles > 0) fileStats.push('- 🔧 Go files: ' + goFiles); + if (jsFiles > 0) fileStats.push('- 🎨 JavaScript files: ' + jsFiles); + if (tsFiles > 0) fileStats.push('- 🎨 TypeScript files: ' + tsFiles); + if (mdFiles > 0) fileStats.push('- 📝 Markdown files: ' + mdFiles); + if (otherFiles > 0) fileStats.push('- 📦 Other files: ' + otherFiles); + const fileStatsText = fileStats.join('\n'); + + const templateUrl = 'https://raw.githubusercontent.com/' + context.repo.owner + '/' + context.repo.repo + '/dev/.github/PULL_REQUEST_TEMPLATE/' + suggestedTemplate + '.md'; + + const comment = '## ' + templateEmoji + ' 建议使用专用模板 | Suggested Template\n\n' + + '您的PR主要包含 **' + suggestedTemplate + '** 相关的变更。我们建议使用更适合的模板以简化填写。\n\n' + + 'Your PR primarily contains **' + suggestedTemplate + '** changes. We suggest using a more suitable template to simplify filling.\n\n' + + '**文件统计 | File Statistics**\n' + fileStatsText + '\n\n' + + '**推荐模板 | Recommended Template**\n```\n.github/PULL_REQUEST_TEMPLATE/' + suggestedTemplate + '.md\n```\n\n' + + '**如何使用 | How to use**\n' + + '1. 编辑PR描述 | Edit PR description\n' + + '2. 复制 [' + suggestedTemplate + ' 模板内容](' + templateUrl + ') | Copy [' + suggestedTemplate + ' template content](' + templateUrl + ')\n' + + '3. 或在创建PR时使用URL参数 | Or use URL parameter when creating PR\n' + + ' `?template=' + suggestedTemplate + '.md`\n\n' + + '_这是一个自动建议,您可以继续使用当前模板。_\n\n' + + '_This is an automated suggestion. You may continue using the current template._'; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: comment + }); + } + } else if (suggestedTemplate && !usingDefaultTemplate) { + console.log('PR already uses a specific template'); + } else { + console.log('No specific template suggestion needed - mixed changes'); + } diff --git a/README.md b/README.md index d79da543..4a82bfed 100644 --- a/README.md +++ b/README.md @@ -281,7 +281,7 @@ Docker automatically handles all dependencies (Go, Node.js, TA-Lib, SQLite) and #### Step 1: Prepare Configuration ```bash # Copy configuration template -cp config.example.jsonc config.json +cp config.json.example config.json # Edit and fill in your API keys nano config.json # or use any editor diff --git a/docker-compose.yml b/docker-compose.yml index a9d35026..dc25bb44 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,6 +17,7 @@ services: - /etc/localtime:/etc/localtime:ro # Sync host time environment: - TZ=${NOFX_TIMEZONE:-Asia/Shanghai} # Set timezone + - AI_MAX_TOKENS=4000 # AI响应的最大token数(默认2000,建议4000-8000) networks: - nofx-network healthcheck: diff --git a/docs/getting-started/README.md b/docs/getting-started/README.md index c35926f9..9e1740f7 100644 --- a/docs/getting-started/README.md +++ b/docs/getting-started/README.md @@ -23,7 +23,7 @@ Choose the method that best fits your needs: **Quick Start:** ```bash -cp config.example.jsonc config.json +cp config.json.example config.json ./start.sh start --build ``` diff --git a/docs/getting-started/README.zh-CN.md b/docs/getting-started/README.zh-CN.md index aafe5cfb..836619f6 100644 --- a/docs/getting-started/README.zh-CN.md +++ b/docs/getting-started/README.zh-CN.md @@ -21,7 +21,7 @@ **快速开始:** ```bash -cp config.example.jsonc config.json +cp config.json.example config.json ./start.sh start --build ``` diff --git a/docs/getting-started/docker-deploy.en.md b/docs/getting-started/docker-deploy.en.md index bd909273..7cb4e3d2 100644 --- a/docs/getting-started/docker-deploy.en.md +++ b/docs/getting-started/docker-deploy.en.md @@ -50,7 +50,7 @@ docker compose --version # Docker 24+ includes this, no separate installation n ```bash # Copy configuration template -cp config.example.jsonc config.json +cp config.json.example config.json # Edit configuration file with your API keys nano config.json # or use any other editor @@ -267,7 +267,7 @@ kill -9 # ~~ls -la config.json~~ # ~~If not exists, copy template~~ -# ~~cp config.example.jsonc config.json~~ +# ~~cp config.json.example config.json~~ *Note: Now using SQLite database for configuration storage, no longer need config.json* ``` diff --git a/docs/getting-started/docker-deploy.zh-CN.md b/docs/getting-started/docker-deploy.zh-CN.md index 49667356..0840ea50 100644 --- a/docs/getting-started/docker-deploy.zh-CN.md +++ b/docs/getting-started/docker-deploy.zh-CN.md @@ -55,7 +55,7 @@ docker compose --version # Docker 24+ 自带,无需单独安装 ```bash # 复制配置文件模板 -cp config.example.jsonc config.json +cp config.json.example config.json # 编辑配置文件,填入你的 API 密钥 nano config.json # 或使用其他编辑器 @@ -270,7 +270,7 @@ kill -9 ls -la config.json # 如果不存在,复制模板 -cp config.example.jsonc config.json +cp config.json.example config.json ``` ### 健康检查失败 diff --git a/docs/i18n/ru/README.md b/docs/i18n/ru/README.md index ac52fb00..cfdc50a1 100644 --- a/docs/i18n/ru/README.md +++ b/docs/i18n/ru/README.md @@ -285,7 +285,7 @@ Docker автоматически обрабатывает все зависим #### Шаг 1: Подготовьте конфигурацию ```bash # Скопируйте шаблон конфигурации -cp config.example.jsonc config.json +cp config.json.example config.json # Отредактируйте и заполните ваши API ключи nano config.json # или используйте любой редактор @@ -423,7 +423,7 @@ cd .. **Шаг 1**: Скопируйте и переименуйте файл примера конфигурации ```bash -cp config.example.jsonc config.json +cp config.json.example config.json ``` **Шаг 2**: Отредактируйте `config.json` и заполните ваши API ключи diff --git a/docs/i18n/uk/README.md b/docs/i18n/uk/README.md index db1a9c59..58bf32ac 100644 --- a/docs/i18n/uk/README.md +++ b/docs/i18n/uk/README.md @@ -288,7 +288,7 @@ Docker автоматично обробляє всі залежності (Go, #### Крок 1: Підготуйте конфігурацію ```bash # Скопіюйте шаблон конфігурації -cp config.example.jsonc config.json +cp config.json.example config.json # Відредагуйте та заповніть ваші API ключі nano config.json # або використайте будь-який редактор @@ -426,7 +426,7 @@ cd .. **Крок 1**: Скопіюйте та перейменуйте файл прикладу конфігурації ```bash -cp config.example.jsonc config.json +cp config.json.example config.json ``` **Крок 2**: Відредагуйте `config.json` та заповніть ваші API ключі diff --git a/docs/i18n/zh-CN/README.md b/docs/i18n/zh-CN/README.md index f22c987a..0311a80d 100644 --- a/docs/i18n/zh-CN/README.md +++ b/docs/i18n/zh-CN/README.md @@ -283,7 +283,7 @@ Docker会自动处理所有依赖(Go、Node.js、TA-Lib)和环境配置, #### 步骤1:准备配置文件 ```bash # 复制配置文件模板 -cp config.example.jsonc config.json +cp config.json.example config.json # 编辑并填入你的API密钥 nano config.json # 或使用其他编辑器 @@ -422,7 +422,7 @@ cd .. ~~**步骤1**:复制并重命名示例配置文件~~ ```bash -cp config.example.jsonc config.json +cp config.json.example config.json ``` ~~**步骤2**:编辑`config.json`填入您的API密钥~~ diff --git a/main.go b/main.go index 8aa83dde..9e9d1aa7 100644 --- a/main.go +++ b/main.go @@ -64,15 +64,15 @@ func syncConfigToDatabase(database *config.Database) error { // 同步各配置项到数据库 configs := map[string]string{ - "admin_mode": fmt.Sprintf("%t", configFile.AdminMode), - "beta_mode": fmt.Sprintf("%t", configFile.BetaMode), - "api_server_port": strconv.Itoa(configFile.APIServerPort), - "use_default_coins": fmt.Sprintf("%t", configFile.UseDefaultCoins), - "coin_pool_api_url": configFile.CoinPoolAPIURL, - "oi_top_api_url": configFile.OITopAPIURL, - "max_daily_loss": fmt.Sprintf("%.1f", configFile.MaxDailyLoss), - "max_drawdown": fmt.Sprintf("%.1f", configFile.MaxDrawdown), - "stop_trading_minutes": strconv.Itoa(configFile.StopTradingMinutes), + "admin_mode": fmt.Sprintf("%t", configFile.AdminMode), + "beta_mode": fmt.Sprintf("%t", configFile.BetaMode), + "api_server_port": strconv.Itoa(configFile.APIServerPort), + "use_default_coins": fmt.Sprintf("%t", configFile.UseDefaultCoins), + "coin_pool_api_url": configFile.CoinPoolAPIURL, + "oi_top_api_url": configFile.OITopAPIURL, + "max_daily_loss": fmt.Sprintf("%.1f", configFile.MaxDailyLoss), + "max_drawdown": fmt.Sprintf("%.1f", configFile.MaxDrawdown), + "stop_trading_minutes": strconv.Itoa(configFile.StopTradingMinutes), } // 同步default_coins(转换为JSON字符串存储) @@ -112,7 +112,7 @@ func syncConfigToDatabase(database *config.Database) error { // loadBetaCodesToDatabase 加载内测码文件到数据库 func loadBetaCodesToDatabase(database *config.Database) error { betaCodeFile := "beta_codes.txt" - + // 检查内测码文件是否存在 if _, err := os.Stat(betaCodeFile); os.IsNotExist(err) { log.Printf("📄 内测码文件 %s 不存在,跳过加载", betaCodeFile) @@ -126,7 +126,7 @@ func loadBetaCodesToDatabase(database *config.Database) error { } log.Printf("🔄 发现内测码文件 %s (%.1f KB),开始加载...", betaCodeFile, float64(fileInfo.Size())/1024) - + // 加载内测码到数据库 err = database.LoadBetaCodesFromFile(betaCodeFile) if err != nil { diff --git a/market/monitor.go b/market/monitor.go index 23e126d9..033e1685 100644 --- a/market/monitor.go +++ b/market/monitor.go @@ -121,19 +121,19 @@ func (m *WSMonitor) Start(coins []string) { // 初始化交易对 err := m.Initialize(coins) if err != nil { - log.Fatalf("❌ 初始化币种: %v", err) + log.Printf("❌ 初始化币种失败: %v", err) return } err = m.combinedClient.Connect() if err != nil { - log.Fatalf("❌ 批量订阅流: %v", err) + log.Printf("❌ 批量订阅流失败: %v", err) return } // 订阅所有交易对 err = m.subscribeAll() if err != nil { - log.Fatalf("❌ 订阅币种交易对: %v", err) + log.Printf("❌ 订阅币种交易对失败: %v", err) return } } @@ -159,7 +159,7 @@ func (m *WSMonitor) subscribeAll() error { for _, st := range subKlineTime { err := m.combinedClient.BatchSubscribeKlines(m.symbols, st) if err != nil { - log.Fatalf("❌ 订阅3m K线: %v", err) + log.Printf("❌ 订阅 %s K线失败: %v", st, err) return err } } diff --git a/mcp/client.go b/mcp/client.go index 9191dfaf..65897b7f 100644 --- a/mcp/client.go +++ b/mcp/client.go @@ -7,6 +7,8 @@ import ( "io" "log" "net/http" + "os" + "strconv" "strings" "time" ) @@ -28,15 +30,28 @@ type Client struct { Model string Timeout time.Duration UseFullURL bool // 是否使用完整URL(不添加/chat/completions) + MaxTokens int // AI响应的最大token数 } func New() *Client { + // 从环境变量读取 MaxTokens,默认 2000 + maxTokens := 2000 + if envMaxTokens := os.Getenv("AI_MAX_TOKENS"); envMaxTokens != "" { + if parsed, err := strconv.Atoi(envMaxTokens); err == nil && parsed > 0 { + maxTokens = parsed + log.Printf("🔧 [MCP] 使用环境变量 AI_MAX_TOKENS: %d", maxTokens) + } else { + log.Printf("⚠️ [MCP] 环境变量 AI_MAX_TOKENS 无效 (%s),使用默认值: %d", envMaxTokens, maxTokens) + } + } + // 默认配置 return &Client{ - Provider: ProviderDeepSeek, - BaseURL: "https://api.deepseek.com/v1", - Model: "deepseek-chat", - Timeout: 120 * time.Second, // 增加到120秒,因为AI需要分析大量数据 + Provider: ProviderDeepSeek, + BaseURL: "https://api.deepseek.com/v1", + Model: "deepseek-chat", + Timeout: 120 * time.Second, // 增加到120秒,因为AI需要分析大量数据 + MaxTokens: maxTokens, } } @@ -81,7 +96,7 @@ func (client *Client) SetQwenAPIKey(apiKey string, customURL string, customModel client.Model = customModel log.Printf("🔧 [MCP] Qwen 使用自定义 Model: %s", customModel) } else { - client.Model = "qwen-plus" // 可选: qwen-turbo, qwen-plus, qwen-max + client.Model = "qwen3-max" log.Printf("🔧 [MCP] Qwen 使用默认 Model: %s", client.Model) } // 打印 API Key 的前后各4位用于验证 @@ -190,7 +205,7 @@ func (client *Client) callOnce(systemPrompt, userPrompt string) (string, error) "model": client.Model, "messages": messages, "temperature": 0.5, // 降低temperature以提高JSON格式稳定性 - "max_tokens": 2000, + "max_tokens": client.MaxTokens, } // 注意:response_format 参数仅 OpenAI 支持,DeepSeek/Qwen 不支持 diff --git a/prompts/adaptive.txt b/prompts/adaptive.txt index d5778caa..3d9657f6 100644 --- a/prompts/adaptive.txt +++ b/prompts/adaptive.txt @@ -61,21 +61,24 @@ ## 开平仓动作 -1. **buy_to_enter**: 开多仓(看涨) +1. **open_long**: 开多仓(看涨) - 用于: 看涨信号强烈时 - 必须设置: 止损价格、止盈价格 -2. **sell_to_enter**: 开空仓(看跌) +2. **open_short**: 开空仓(看跌) - 用于: 看跌信号强烈时 - 必须设置: 止损价格、止盈价格 -3. **close**: 完全平仓 - - 用于: 止盈、止损、或趋势反转 +3. **close_long**: 平掉多仓 + - 用于: 止盈、止损、或趋势反转(针对多头持仓) -4. **wait**: 观望,不持仓 +4. **close_short**: 平掉空仓 + - 用于: 止盈、止损、或趋势反转(针对空头持仓) + +5. **wait**: 观望,不持仓 - 用于: 没有明确信号,或资金不足 -5. **hold**: 持有当前仓位 +6. **hold**: 持有当前仓位 - 用于: 持仓表现符合预期,继续等待 ## 动态调整动作 (新增) diff --git a/prompts/nof1.txt b/prompts/nof1.txt index 012daa62..2e707b01 100644 --- a/prompts/nof1.txt +++ b/prompts/nof1.txt @@ -21,19 +21,25 @@ Your mission: Maximize risk-adjusted returns (PnL) through systematic, disciplin # ACTION SPACE DEFINITION -You have exactly FOUR possible actions per decision cycle: +You have exactly SIX possible actions per decision cycle: -1. **buy_to_enter**: Open a new LONG position (bet on price appreciation) +1. **open_long**: Open a new LONG position (bet on price appreciation) - Use when: Bullish technical setup, positive momentum, risk-reward favors upside -2. **sell_to_enter**: Open a new SHORT position (bet on price depreciation) +2. **open_short**: Open a new SHORT position (bet on price depreciation) - Use when: Bearish technical setup, negative momentum, risk-reward favors downside -3. **hold**: Maintain current positions without modification +3. **close_long**: Exit an existing LONG position entirely + - Use when: Profit target reached, stop loss triggered, or thesis invalidated (for long positions) + +4. **close_short**: Exit an existing SHORT position entirely + - Use when: Profit target reached, stop loss triggered, or thesis invalidated (for short positions) + +5. **hold**: Maintain current positions without modification - Use when: Existing positions are performing as expected, or no clear edge exists -4. **close**: Exit an existing position entirely - - Use when: Profit target reached, stop loss triggered, or thesis invalidated +6. **wait**: Do not open any new positions, no current holdings + - Use when: No clear trading signal or insufficient capital ## Position Management Constraints diff --git a/trader/auto_trader.go b/trader/auto_trader.go index 9a68ed17..c489fcc3 100644 --- a/trader/auto_trader.go +++ b/trader/auto_trader.go @@ -257,9 +257,9 @@ func (at *AutoTrader) Stop() { func (at *AutoTrader) runCycle() error { at.callCount++ - log.Print("\n" + strings.Repeat("=", 70)) + log.Print("\n" + strings.Repeat("=", 70) + "\n") log.Printf("⏰ %s - AI决策周期 #%d", time.Now().Format("2006-01-02 15:04:05"), at.callCount) - log.Print(strings.Repeat("=", 70)) + log.Println(strings.Repeat("=", 70)) // 创建决策记录 record := &logger.DecisionRecord{ @@ -346,19 +346,19 @@ func (at *AutoTrader) runCycle() error { // 打印系统提示词和AI思维链(即使有错误,也要输出以便调试) if decision != nil { if decision.SystemPrompt != "" { - log.Print("\n" + strings.Repeat("=", 70)) + log.Print("\n" + strings.Repeat("=", 70) + "\n") log.Printf("📋 系统提示词 [模板: %s] (错误情况)", at.systemPromptTemplate) log.Println(strings.Repeat("=", 70)) log.Println(decision.SystemPrompt) - log.Print(strings.Repeat("=", 70) + "\n") + log.Println(strings.Repeat("=", 70)) } if decision.CoTTrace != "" { - log.Print("\n" + strings.Repeat("-", 70)) + log.Print("\n" + strings.Repeat("-", 70) + "\n") log.Println("💭 AI思维链分析(错误情况):") log.Println(strings.Repeat("-", 70)) log.Println(decision.CoTTrace) - log.Print(strings.Repeat("-", 70) + "\n") + log.Println(strings.Repeat("-", 70)) } } diff --git a/web/public/images/guide.png b/web/public/images/guide.png new file mode 100644 index 00000000..cd1abd2e Binary files /dev/null and b/web/public/images/guide.png differ diff --git a/web/src/components/AITradersPage.tsx b/web/src/components/AITradersPage.tsx index b2563ef3..6f8d761c 100644 --- a/web/src/components/AITradersPage.tsx +++ b/web/src/components/AITradersPage.tsx @@ -8,7 +8,7 @@ import { useAuth } from '../contexts/AuthContext'; import { getExchangeIcon } from './ExchangeIcons'; import { getModelIcon } from './ModelIcons'; import { TraderConfigModal } from './TraderConfigModal'; -import { Bot, Brain, Landmark, BarChart3, Trash2, Plus, Users, AlertTriangle } from 'lucide-react'; +import { Bot, Brain, Landmark, BarChart3, Trash2, Plus, Users, AlertTriangle, BookOpen } from 'lucide-react'; // 获取友好的AI模型名称 function getModelDisplayName(modelId: string): string { @@ -1094,7 +1094,7 @@ function ModelConfigModal({ type="text" value={modelName} onChange={(e) => setModelName(e.target.value)} - placeholder="例如: deepseek-chat, qwen-max, gpt-5" + placeholder="例如: deepseek-chat, qwen3-max, gpt-5" className="w-full px-3 py-2 rounded" style={{ background: '#0B0E11', border: '1px solid #2B3139', color: '#EAECEF' }} /> @@ -1161,7 +1161,9 @@ function ExchangeConfigModal({ const [secretKey, setSecretKey] = useState(''); const [passphrase, setPassphrase] = useState(''); const [testnet, setTestnet] = useState(false); - + const [showGuide, setShowGuide] = useState(false); + + // Aster 特定字段 const [asterUser, setAsterUser] = useState(''); const [asterSigner, setAsterSigner] = useState(''); @@ -1219,21 +1221,34 @@ function ExchangeConfigModal({

{editingExchangeId ? t('editExchange', language) : t('addExchange', language)}

- {editingExchangeId && ( - - )} +
+ {selectedExchange?.id === 'binance' && ( + + )} + {editingExchangeId && ( + + )} +
@@ -1458,6 +1473,34 @@ function ExchangeConfigModal({
+ + {/* Binance Setup Guide Modal */} + {showGuide && ( +
setShowGuide(false)}> +
e.stopPropagation()}> +
+

+ + {t('binanceSetupGuide', language)} +

+ +
+
+ {t('binanceSetupGuide', +
+
+
+ )} ); } diff --git a/web/src/i18n/translations.ts b/web/src/i18n/translations.ts index 99a11cac..f69ca1f1 100644 --- a/web/src/i18n/translations.ts +++ b/web/src/i18n/translations.ts @@ -257,6 +257,9 @@ export const translations = { exchangeConfigWarning2: '• Do not grant withdrawal permissions to ensure fund security', exchangeConfigWarning3: '• After deleting configuration, related traders will not be able to trade', edit: 'Edit', + viewGuide: 'View Guide', + binanceSetupGuide: 'Binance Setup Guide', + closeGuide: 'Close', // Error Messages createTraderFailed: 'Failed to create trader', @@ -671,6 +674,9 @@ export const translations = { exchangeConfigWarning2: '• 不要授予提现权限,确保资金安全', exchangeConfigWarning3: '• 删除配置后,相关交易员将无法正常交易', edit: '编辑', + viewGuide: '查看教程', + binanceSetupGuide: '币安配置教程', + closeGuide: '关闭', // Error Messages createTraderFailed: '创建交易员失败',