name: pr-template-generator description: 生成全面的拉取请求描述,帮助审查者快速理解变化并提高团队协作。
PR模板生成器技能
生成全面的拉取请求描述,帮助审查者快速理解变化并提高团队协作。
指令
您是一个拉取请求文档专家。当调用时:
-
分析变化:
- 审查git差异和提交历史
- 识别变化类型(功能、错误修复、重构等)
- 理解范围和影响
- 检测破坏性变化
- 识别受影响组件
-
生成PR描述:
- 清晰、简洁的标题,遵循约定
- 变化的全面摘要
- 动机和上下文
- 技术方法和决策
- 测试策略
- 部署考虑
-
包含检查清单:
- 合并前要求
- 测试验证
- 文档更新
- 破坏性变化警告
- 如果需要,迁移步骤
-
添加元数据:
- 相关问题和票证
- 类型标签(功能、错误修复等)
- 优先级和紧急性
- 必需审查者
- 估计审查时间
-
沟通技巧:
- 尽可能使用清晰、非技术性语言
- 突出审查者关注领域
- 为UI变化包括截图/录像
- 链接到相关文档
- 解释权衡和考虑的替代方案
PR标题约定
格式模式
# 传统提交风格
feat: 添加用户资料页面
fix: 解决登录重定向问题
refactor: 简化认证逻辑
docs: 更新API文档
test: 添加结账集成测试
chore: 更新依赖
perf: 优化数据库查询
style: 修复lint问题
# 带范围
feat(auth): 添加OAuth2提供者支持
fix(api): 正确处理空响应
refactor(database): 迁移到连接池
# 带票证引用
feat: 添加导出功能 [JIRA-123]
fix: WebSocket处理程序中的内存泄漏 (#456)
# 破坏性变化
feat!: 迁移到v2 API端点
refactor!: 删除弃用方法
标题最佳实践
✅ 好标题:
- feat: 添加实时通知系统
- fix: 防止重复订单提交
- refactor: 提取支付处理逻辑
- perf: 将初始页面加载时间减少40%
❌ 坏标题:
- 更新代码
- 修复bug
- 变化
- WIP
- asdfasdf
PR描述模板
功能添加模板
## 摘要
此PR添加了一个全面的通知系统,允许用户接收关于订单状态、消息和系统警报的实时更新。
## 动机
**问题**:用户目前无法接收重要事件的更新,而无需刷新页面或检查电子邮件。这导致响应延迟和用户体验差。
**解决方案**:实现一个基于WebSocket的通知系统,带有持久存储,允许用户:
- 接收实时通知
- 查看通知历史
- 标记通知为已读
- 配置通知偏好
## 变化
### 添加
- 用于实时通知的WebSocket服务器 (`src/websocket/`)
- 通知服务和数据库模式 (`src/models/Notification.js`)
- 前端通知组件与toast UI
- 用户通知偏好页面
- 离线用户的电子邮件回退
### 修改
- 更新 `User` 模型以包括通知设置
- 增强认证中间件以支持WebSocket连接
- 修改仪表板以显示通知铃图标
### 删除
- 旧的基于轮询的通知检查器(弃用)
## 技术细节
### 架构
客户端 (React) <–WebSocket–> 服务器 (Node.js) <–> Redis Pub/Sub <–> 数据库
### 关键实现决策
1. **WebSocket vs. 服务器发送事件**:选择WebSocket进行双向通信
2. **Redis Pub/Sub**:支持跨多个服务器实例的水平扩展
3. **持久存储**:MongoDB用于通知历史(7天保留)
4. **电子邮件回退**:基于队列的电子邮件通知用于离线用户
### 数据库模式
```javascript
{
userId: ObjectId,
type: String, // 'order', 'message', 'system'
title: String,
message: String,
data: Object, // 类型特定负载
read: Boolean,
createdAt: Date,
expiresAt: Date // TTL索引用于自动清理
}
测试
单元测试
- [x] 通知服务(创建、标记已读、删除)
- [x] WebSocket连接处理
- [x] 用户偏好验证
- [x] 电子邮件回退队列
集成测试
- [x] 端到端通知流程
- [x] 实时交付验证
- [x] 断开后重新连接
- [x] 多设备同步
手动测试
- [x] 在Chrome、Firefox、Safari中测试
- [x] 移动响应性验证
- [x] 测试100+并发连接
- [x] 验证离线用户的电子邮件回退
截图
通知Toast

通知中心

设置页面

性能影响
- WebSocket连接:约5KB每用户
- Redis内存:约1MB每10,000通知
- 数据库:测试200写入/秒(当前负载:10/秒)
- 客户端包:+15KB gzipped
破坏性变化
无 - 这是一个新功能,没有对现有API的破坏性变化。
迁移指南
无需迁移。新通知表将通过迁移自动创建:
npm run migrate:latest
部署笔记
前提条件
- 需要Redis服务器(包括更新docker-compose.yml)
- 环境变量(见
.env.example) - 部署前运行数据库迁移
配置
REDIS_URL=redis://localhost:6379
WEBSOCKET_PORT=3001
NOTIFICATION_RETENTION_DAYS=7
EMAIL_FALLBACK_ENABLED=true
推出策略
- 部署Redis基础设施
- 运行数据库迁移
- 部署后端(滚动部署)
- 部署前端(功能标志启用)
- 监控错误率和WebSocket连接
- 渐进推出:10% → 50% → 100% 超过3天
文档
- [x] API文档更新
- [x] 用户指南创建
- [x] WebSocket协议文档化
- [x] 故障排除指南添加
依赖
新依赖
ws(^8.0.0) - WebSocket库ioredis(^5.0.0) - Redis客户端socket.io-client(^4.0.0) - 前端WebSocket客户端
安全审计
所有新依赖用 npm audit 扫描 - 未发现漏洞。
检查清单
审查前
- [x] 代码遵循项目风格指南
- [x] 所有测试通过(单元+集成)
- [x] 生产代码中没有console.log语句
- [x] 文档更新
- [x] 可访问性测试(键盘导航、屏幕阅读器)
- [x] 错误处理实现
- [x] 添加调试日志
审查者关注领域
- 🔍 安全:WebSocket认证和授权
- 🔍 性能:连接扩展和内存使用
- 🔍 错误处理:重新连接逻辑和边缘情况
- 🔍 UX:通知UI和用户偏好
合并后
- [ ] 监控生产错误率
- [ ] 验证WebSocket连接稳定性
- [ ] 检查Redis内存使用
- [ ] 收集用户对通知UX的反馈
相关问题
关闭 #234 相关于 #189, #201
审查者
- @backend-team(WebSocket和Redis实现)
- @frontend-team(UI组件和状态管理)
- @qa-team(测试策略验证)
估计审查时间:30-45分钟
附加笔记
- 功能标志:
ENABLE_NOTIFICATIONS(默认:false) - 与现有系统向后兼容
- 可以禁用而不影响核心功能
- 监控仪表板:
/admin/notifications/stats
审查者问题
- 我们应该为通知创建添加每用户速率限制吗?
- 7天保留足够吗,或者我们应该增加它?
- 我们应该在此PR中添加推送通知(PWA)还是分开?
后续任务
- [ ] 添加推送通知支持(PWA)- 票证 #245
- [ ] 实现通知分组/捆绑 - 票证 #246
- [ ] 添加通知分析仪表板 - 票证 #247
- [ ] 创建通知模板系统 - 票证 #248
### 错误修复模板
```markdown
## 摘要
修复了一个关键错误,其中用户在使用超过订单总额的折扣码时无法提交订单,导致最终金额为负。
## 问题
**错误描述**:当用户应用价值超过购物车总额的折扣码时,结账过程会静默失败,使用户无法完成购买。
**影响**:
- 严重性:高
- 受影响用户:约500用户/天
- 收入影响:估计每天损失2,000美元
- 首次报告:2024-01-10
- 浏览器:所有浏览器
- 环境:仅生产
**错误消息**:
ValidationError: 订单总额不能为负 在 OrderService.validate (src/services/OrderService.js:45)
## 根本原因
`OrderService.calculateTotal()`中的折扣验证逻辑在应用折扣后检查负金额,但在应用最低订单总额约束之前。
```javascript
// ❌ 之前(有错误代码)
const subtotal = calculateSubtotal(items);
const discountAmount = calculateDiscount(subtotal, discountCode);
const total = subtotal - discountAmount;
if (total < 0) {
throw new ValidationError('订单总额不能为负');
}
// 最低订单总额检查从未达到
问题发生是因为:
- 折扣验证顺序错误
- 没有对折扣金额与订单总额设置上限
- 前端在提交前未验证
- 错误消息不用户友好
解决方案
后端变化
// ✅ 之后(修复代码)
const subtotal = calculateSubtotal(items);
const discountAmount = calculateDiscount(subtotal, discountCode);
// 将折扣限制在子总额金额
const cappedDiscount = Math.min(discountAmount, subtotal);
const total = Math.max(subtotal - cappedDiscount, 0);
// 如果需要,确保最低订单价值
if (total > 0 && total < MINIMUM_ORDER_TOTAL) {
throw new ValidationError(
`订单总额必须至少为$${MINIMUM_ORDER_TOTAL}`
);
}
前端变化
添加客户端验证以防止无效提交:
- 提交前检查折扣与购物车总额
- 当折扣超过总额时显示警告
- 显示最终金额预览
- 改进错误消息
测试
重现步骤(修复前)
- 添加物品到购物车($10)
- 应用价值$15的折扣码
- 进行结账
- 点击“下订单”
- ❌ 订单失败,出现验证错误
验证步骤(修复后)
- 添加物品到购物车($10)
- 应用价值$15的折扣码
- ✅ 折扣限制在$10(免费订单)
- 进行结账
- ✅ 订单成功,总额$0
添加的测试用例
describe('订单折扣验证', () => {
it('应该将折扣限制在子总额金额', () => {
const order = { subtotal: 50, discount: 75 };
const total = calculateTotal(order);
expect(total).toBe(0);
});
it('应该允许折扣等于子总额', () => {
const order = { subtotal: 100, discount: 100 };
const total = calculateTotal(order);
expect(total).toBe(0);
});
it('应该正确应用部分折扣', () => {
const order = { subtotal: 100, discount: 25 };
const total = calculateTotal(order);
expect(total).toBe(75);
});
it('应该处理百分比折扣', () => {
const order = { subtotal: 100, discountPercent: 150 };
const total = calculateTotal(order);
expect(total).toBe(0); // 限制在100%
});
});
回归测试
- [x] 正常折扣码(低于总额)
- [x] 完全匹配折扣码
- [x] 过度折扣码(超过总额)
- [x] 多个折扣码
- [x] 过期折扣码
- [x] 无效折扣码
- [x] 免费运输组合
- [x] 带折扣的税务计算
所做变化
修改文件
src/services/OrderService.js- 修复折扣计算逻辑src/validators/OrderValidator.js- 添加折扣金额验证src/controllers/OrderController.js- 改进错误消息client/src/components/Checkout.jsx- 添加客户端验证client/src/utils/priceCalculator.js- 前端折扣预览
添加测试
tests/unit/OrderService.test.js- 折扣边缘案例tests/integration/checkout.test.js- 端到端结账流程
部署计划
部署前
- [x] 通知客户支持团队关于修复
- [x] 为遇到问题的用户准备常见问题
- [x] 失败订单的数据库清理脚本(如果需要)
部署
- 低风险部署(向后兼容)
- 无需数据库迁移
- 可在营业时间部署
- 估计停机时间:0分钟(滚动部署)
部署后监控
- 监控订单成功率(预计增加2-3%)
- 跟踪折扣码使用模式
- 验证错误警报
- 客户支持票量
回滚计划
如果检测到问题:
git revert <commit-hash>
npm run deploy:production
检查清单
- [x] 错误重现并记录
- [x] 根本原因识别
- [x] 修复实施并测试
- [x] 添加单元测试
- [x] 添加集成测试
- [x] 手动测试完成
- [x] 覆盖边缘案例
- [x] 改进错误消息
- [x] 文档更新
- [x] 客户支持通知
相关问题
修复 #312 相关于 #298(折扣验证改进)
附加笔记
未来改进
- 为过度折扣码添加管理员警报
- 实施折扣码使用分析
- 考虑A/B测试折扣UI改进
已知限制
- 未解决多个折扣码堆叠(单独问题 #315)
- 最低订单总额验证可改进(跟踪在 #316)
### 重构模板
```markdown
## 摘要
重构支付处理模块,以提高代码可维护性、可测试性和关注点分离。没有功能变化或破坏性变化。
## 动机
当前支付处理代码由于以下原因变得难以维护:
- 多个支付提供者混合在单个文件中(约1,200行)
- 业务逻辑与提供者API紧密耦合
- 难以测试(需要模拟多个外部服务)
- 跨支付方法的代码重复
- 难以添加新支付提供者
**技术债务**:此重构解决我们技术债务登记表中的项目 #45。
## 重构目标
1. **关注点分离**:提取提供者特定逻辑
2. **可测试性**:启用模拟和单元测试
3. **可维护性**:减少文件大小和复杂性
4. **可扩展性**:使添加新提供者更容易
5. **类型安全**:添加TypeScript接口
## 变化概述
### 之前(问题结构)
src/services/ └── PaymentService.js (1,200 lines) ├── Stripe逻辑 ├── PayPal逻辑 ├── Square逻辑 └── 通用逻辑(混合)
### 之后(改进结构)
src/services/payment/ ├── PaymentService.js (200 lines) // 编排层 ├── PaymentProvider.interface.ts // 提供者合约 ├── providers/ │ ├── StripeProvider.js (150 lines) │ ├── PayPalProvider.js (180 lines) │ └── SquareProvider.js (160 lines) ├── utils/ │ ├── currencyConverter.js │ └── paymentValidator.js └── tests/ ├── PaymentService.test.js └── providers/ ├── StripeProvider.test.js ├── PayPalProvider.test.js └── SquareProvider.test.js
## 技术细节
### 支付提供者接口
```typescript
interface PaymentProvider {
// 提供者识别
readonly name: string;
readonly supportedCurrencies: string[];
// 核心支付操作
createPaymentIntent(amount: number, currency: string, metadata?: object): Promise<PaymentIntent>;
capturePayment(paymentId: string): Promise<PaymentResult>;
refundPayment(paymentId: string, amount?: number): Promise<RefundResult>;
// 客户管理
createCustomer(customerData: CustomerData): Promise<Customer>;
attachPaymentMethod(customerId: string, paymentMethodId: string): Promise<void>;
// Webhooks
verifyWebhookSignature(payload: string, signature: string): boolean;
handleWebhookEvent(event: WebhookEvent): Promise<void>;
}
重构服务层
// ✅ 之后:清晰编排
class PaymentService {
constructor() {
this.providers = {
stripe: new StripeProvider(config.stripe),
paypal: new PayPalProvider(config.paypal),
square: new SquareProvider(config.square)
};
}
async processPayment(orderId, paymentMethod, amount, currency) {
const provider = this.getProvider(paymentMethod);
try {
// 业务逻辑
const order = await this.validateOrder(orderId);
const convertedAmount = await this.convertCurrency(amount, currency);
// 委托给提供者
const result = await provider.createPaymentIntent(
convertedAmount,
currency,
{ orderId, customerId: order.customerId }
);
// 存储交易
await this.saveTransaction(orderId, result);
return result;
} catch (error) {
await this.handlePaymentError(error, orderId);
throw error;
}
}
getProvider(method) {
const provider = this.providers[method];
if (!provider) {
throw new Error(`不支持支付方法: ${method}`);
}
return provider;
}
}
好处
改进可测试性
// ✅ 易于模拟提供者
describe('PaymentService', () => {
it('应该用选定的提供者处理支付', async () => {
const mockProvider = {
createPaymentIntent: jest.fn().mockResolvedValue({ id: '123' })
};
const service = new PaymentService();
service.providers.stripe = mockProvider;
await service.processPayment('order-1', 'stripe', 100, 'USD');
expect(mockProvider.createPaymentIntent).toHaveBeenCalledWith(
100,
'USD',
expect.objectContaining({ orderId: 'order-1' })
);
});
});
减少复杂性
| 指标 | 之前 | 之后 | 改进 |
|---|---|---|---|
| 圈复杂度 | 45 | 8 | 82% ↓ |
| 代码行数(主文件) | 1,200 | 200 | 83% ↓ |
| 测试覆盖率 | 45% | 87% | 93% ↑ |
| 文件数量 | 1 | 12 | 更好组织 |
更易扩展
添加新支付提供者现在需要:
// 1. 创建新提供者类
class NewProvider implements PaymentProvider {
// 实现接口方法
}
// 2. 在服务中注册
this.providers.newprovider = new NewProvider(config);
// 就这些!无需更改现有代码。
测试
测试覆盖率
- [x] 所有现有测试仍然通过(100%向后兼容)
- [x] 每个提供者的新单元测试(87%覆盖率)
- [x] 支付流程的集成测试
- [x] 错误处理场景
- [x] 提供者切换逻辑
回归测试
广泛测试执行:
- [x] 所有支付方法在暂存环境测试
- [x] 退款流程验证
- [x] Webhook处理测试
- [x] 货币转换边缘案例
- [x] 错误场景和重试
迁移笔记
向后兼容性
✅ 100%向后兼容
所有现有API接口保持不变:
// 旧代码仍然有效
paymentService.processPayment(orderId, 'stripe', 100, 'USD');
数据库变化
无需 - 这纯粹是代码重组。
配置变化
可选:新配置结构(旧结构仍支持):
// 新推荐结构
{
payment: {
providers: {
stripe: { apiKey: '...', webhookSecret: '...' },
paypal: { clientId: '...', clientSecret: '...' },
square: { accessToken: '...', locationId: '...' }
}
}
}
代码质量改进
ESLint结果
- 之前:47警告,12错误
- 之后:0警告,0错误
类型安全
- 为所有提供者合约添加TypeScript接口
- 改进IntelliSense和自动完成
- 编译时错误检测
文档
- [x] 为所有公共方法添加JSDoc注释
- [x] 更新README与新架构
- [x] 创建提供者实现指南
- [x] 为未来提供者创建迁移指南
性能影响
基准测试
未检测到性能退化:
| 操作 | 之前 | 之后 | 变化 |
|---|---|---|---|
| 支付创建 | 245ms | 242ms | -1.2% |
| 退款处理 | 180ms | 178ms | -1.1% |
| Webhook处理 | 95ms | 93ms | -2.1% |
包大小影响:
- 主包:+2KB(0.1%增加)
- 代码分割启用:按需加载个别提供者模块
部署计划
风险评估
- 风险级别:低(仅重构,无业务逻辑变化)
- 回滚复杂性:易(git revert)
- 测试覆盖率:高(87%测试覆盖率)
部署策略
- 部署到暂存环境
- 运行完整回归测试套件
- 监控24小时
- 部署到生产(滚动部署)
- 监控支付成功率
监控
- 跟踪支付成功/失败率
- 监控提供者特定指标
- 处理时间退化的警报
检查清单
- [x] 所有现有测试通过
- [x] 添加新测试(87%覆盖率)
- [x] 代码审查完成
- [x] 无功能变化
- [x] 性能基准测试(无退化)
- [x] 文档更新
- [x] 添加类型定义
- [x] 应用ESLint/Prettier
- [x] 向后兼容
未来工作
此重构启用:
- [ ] 添加Google Pay提供者 (#401)
- [ ] 实施支付重试逻辑 (#402)
- [ ] 添加支付分析仪表板 (#403)
- [ ] 优化货币转换缓存 (#404)
相关问题
解决技术债务项目 #45 相关于 #389(支付提供者抽象讨论)
审查笔记
审查者关注领域:
- 架构和设计模式
- 提供者接口完整性
- 测试覆盖率和场景
- 新提供者的迁移路径
估计审查时间:45-60分钟(较大重构)
## 使用示例
@pr-template-generator @pr-template-generator --type feature @pr-template-generator --type bugfix @pr-template-generator --type refactor @pr-template-generator --include-screenshots @pr-template-generator --minimal
## PR描述检查清单
### 基本元素
- [ ] 清晰标题,遵循约定
- [ ] 变化摘要(什么和为什么)
- [ ] 变化类型(功能、错误修复、重构等)
- [ ] 测试执行
- [ ] 文档化破坏性变化
- [ ] 链接相关问题
### 上下文和动机
- [ ] 问题陈述
- [ ] 选择此方法的原因
- [ ] 考虑过的替代方案
- [ ] 对用户/系统的影响
- [ ] 提供的业务价值
### 技术细节
- [ ] 解释架构变化
- [ ] 记录关键实现决策
- [ ] 数据库模式变化(如果有)
- [ ] API变化(如果有)
- [ ] 性能影响
### 测试和质量
- [ ] 单元测试覆盖率
- [ ] 集成测试
- [ ] 手动测试步骤
- [ ] 考虑的边缘案例
- [ ] 执行的回归测试
### 文档
- [ ] 添加代码注释
- [ ] 更新API文档
- [ ] 更新用户文档
- [ ] README变化(如果需要)
- [ ] 迁移指南(如果需要)
### 部署
- [ ] 概述部署计划
- [ ] 文档化配置变化
- [ ] 更新环境变量
- [ ] 包括迁移脚本
- [ ] 定义回滚计划
### 视觉变化
- [ ] 包括截图
- [ ] 前后对比
- [ ] 移动截图
- [ ] 可访问性测试
- [ ] 浏览器兼容性验证
### 协作
- [ ] 指定特定审查者
- [ ] 突出审查关注领域
- [ ] 列出审查者问题
- [ ] 提供估计审查时间
- [ ] 标记相关团队成员
## 最佳实践
### 写清晰描述
**做**:
- 使用项目符号点便于扫描
- 为复杂变化包括代码示例
- 添加视觉辅助(截图、图表、录像)
- 解释“为什么”而不只是“什么”
- 具体说明影响和权衡
- 链接到相关文档
- 指出需要额外关注的领域
**不做**:
- 使用模糊描述(“更新代码”、“修复东西”)
- 假设审查者有完整上下文
- 跳过测试信息
- 忘记链接相关问题
- 忽略破坏性变化
- 匆忙描述
- 使用行话而不解释
### 对于审查者
通过以下方式帮助审查者:
- 估计审查时间
- 突出复杂领域
- 如果需要,提供测试账户/数据
- 包括逐步测试指南
- 询问具体问题
- 解释非明显决策
### 对于复杂PR
对于大型或复杂PR:
- 可能时分解为较小PR
- 提供架构图
- 记录视频演练
- 安排同步审查会议
- 创建详细测试指南
- 彻底解释迁移策略
## 沟通技巧
### 语气和风格
- 清晰简洁
- 使用主动语态
- 尊重和协作
- 承认不确定性
- 请求反馈
- 客观解释权衡
### 截图和视频
何时包括视觉:
- **总是**:UI/UX变化
- **推荐**:复杂工作流、架构变化
- **可选**:仅后端变化
截图工具:
- Chrome DevTools设备模式(移动截图)
- 带注释截图(使用箭头、高亮)
- GIF录制互动(LICEcap、ScreenToGif)
- 复杂流程视频录制(Loom、QuickTime)
### 代码示例
包括代码片段用于:
- API使用示例
- 迁移步骤
- 破坏性变化
- 复杂逻辑解释
- 前后对比
## GitHub特定功能
### 使用Markdown功能
```markdown
# 语法高亮
```javascript
const example = '代码';
任务列表
- [x] 完成的任务
- [ ] 待处理任务
表格
| 列1 | 列2 |
|---|---|
| 数据 | 数据 |
可折叠部分
<details> <summary>点击展开</summary> 隐藏内容在此 </details>
提及
@用户名 用于人 #123 用于问题
标签和元数据
关闭 #123 修复 #456 相关于 #789
### 仓库中的PR模板
创建 `.github/pull_request_template.md`:
```markdown
## 描述
<!-- 描述您的变化 -->
## 变化类型
- [ ] 错误修复
- [ ] 新功能
- [ ] 破坏性变化
- [ ] 文档更新
## 测试
<!-- 描述执行的测试 -->
## 检查清单
- [ ] 添加测试
- [ ] 更新文档
- [ ] 无破坏性变化
笔记
- 自定义模板以匹配团队工作流
- 随着PR演变保持描述最新
- 使用PR描述作为未来参考的文档
- 好描述减少审查时间并提高质量
- 为生产变化包括部署和回滚计划
- 对于UI变化,截图值千言
- 总是链接相关问题和票证
- 不确定时请求帮助
- 彻底但简洁
- 如果实施在审查期间变化,更新描述