npx skills add https://github.com/cacr92/wereply --skill code-review针对 Tauri + Rust + React 应用程序的全面代码审查指导,重点关注质量、安全性和可维护性。
此技能提供系统的代码审查指导,涵盖:
此技能在以下情况激活:
在深入代码细节之前:
# 检查 git diff 上下文
git diff main...feature-branch
git log --oneline main..feature-branch
# 验证测试通过
cargo test
npm test
# 检查格式
cargo fmt --check
npm run lint
需要回答的问题:
git diff --stat)广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
✅ 正确的 Tauri 命令:
#[tauri::command]
#[specta::specta]
pub async fn get_materials(
state: State<'_, TauriAppState>,
) -> ApiResponse<Vec<Material>> {
with_service(state, |ctx| async move {
ctx.material_service.get_all().await
})
.await
}
检查清单:
#[tauri::command] 属性#[specta::specta] 属性ApiResponse<T>with_service 辅助函数或适当的错误处理await✅ 良好的错误处理:
pub async fn create_formula(&self, dto: CreateFormulaDto) -> Result<Formula> {
// 验证输入
if dto.name.is_empty() {
return Err(anyhow!("名称不能为空"));
}
// 检查重复项
if self.exists_by_name(&dto.name).await? {
return Err(anyhow!("配方名称已存在"));
}
// 使用事务创建
let mut tx = self.pool.begin().await?;
let id = self.insert_internal(&dto, &mut tx).await?;
tx.commit().await?;
Ok(self.get_by_id(id).await?)
}
需要警惕的常见问题:
?)let _ = result).context() 进行错误链式处理✅ 安全的 SQLx 查询:
sqlx::query_as!(
Material,
"SELECT code, name, price FROM materials WHERE code = ?",
code
)
.fetch_one(&pool)
.await
常见问题:
SELECT * - 应明确指定列危险信号:
// ❌ 阻塞异步运行时
std::thread::sleep(Duration::from_secs(10));
// ❌ 不必要的克隆
let data = self.large_data.clone(); // 可以使用 &LargeData
// ❌ 低效的数据结构
let mut items = Vec::new();
for item in huge_list {
if items.contains(&item) { // O(n) 查找
items.push(item);
}
}
// ✅ 使用 HashSet 实现 O(1) 查找
use std::collections::HashSet;
let mut items = HashSet::new();
性能检查清单:
Arc 与 & 引用rayon 进行 CPU 密集型任务的并行处理✅ 结构良好的组件:
import React, { useCallback, useMemo } from 'react';
import { message } from 'antd';
interface Props {
formula: Formula;
onUpdate: (id: number) => void;
}
export const FormulaCard: React.FC<Props> = React.memo(({ formula, onUpdate }) => {
const totalCost = useMemo(
() => formula.materials.reduce((sum, m) => sum + m.cost, 0),
[formula.materials]
);
const handleUpdate = useCallback(() => {
onUpdate(formula.id);
}, [formula.id, onUpdate]);
return (
<div>
<h3>{formula.name}</h3>
<p>成本: {totalCost.toFixed(2)}</p>
<Button onClick={handleUpdate}>更新</Button>
</div>
);
});
检查清单:
any)React.memo 提升性能useCallback 处理作为 props 传递的回调函数useMemo 处理昂贵的计算console.log(改用 message)✅ 正确的 Hooks 使用:
export const useFormulas = () => {
const { data, isLoading, error } = useQuery({
queryKey: ['formulas'],
queryFn: () => commands.getFormulas(),
});
const createMutation = useMutation({
mutationFn: (dto: CreateDto) => commands.createFormula(dto),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['formulas'] });
message.success('创建成功');
},
});
return { formulas: data, isLoading, createMutation };
};
常见问题:
useEffect/useCallback 中缺少依赖项setStateinvoke 而不是生成的 commands类型安全检查:
// ✅ 使用生成的类型
import type { Formula, Material } from '../bindings';
import { commands } from '../bindings';
const result = await commands.getFormula(123);
if (!result.success) {
message.error(result.message);
return;
}
const formula: Formula = result.data; // 类型安全!
需要注意的问题:
as any 类型断言result.successSQL 注入:
// ❌ 存在漏洞
let query = format!("SELECT * FROM materials WHERE name = '{}'", name);
sqlx::query(&query).fetch_one(&pool).await
// ✅ 安全
sqlx::query_as!(
Material,
"SELECT * FROM materials WHERE name = ?",
name
)
.fetch_one(&pool).await
输入验证:
// ❌ 无验证
pub fn create_material(name: String, price: f64) -> Result<Material> {
// 直接插入,无检查
}
// ✅ 带验证
pub fn create_material(name: String, price: f64) -> Result<Material> {
if name.is_empty() || name.len() > 100 {
return Err(anyhow!("无效的原料名称"));
}
if price < 0.0 || price > 10000.0 {
return Err(anyhow!("价格超出合理范围"));
}
// 继续创建过程
}
桌面应用安全:
// ✅ 良好的测试覆盖率
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_calculate_cost() {
// 正常情况
assert_eq!(calculate_cost(&materials), 100.0);
// 边界情况
assert_eq!(calculate_cost(&[]), 0.0);
assert_eq!(calculate_cost(&[single_material]), single_material.cost);
}
#[test]
fn test_negative_proportion_rejected() {
let result = validate_proportion(-10.0);
assert!(result.is_err());
}
}
检查清单:
需要检查的内容:
## 🔴 严重:[问题标题]
**位置**:`src/file.rs:42`
**问题**:[对问题的清晰描述]
**影响**:[为什么这很重要]
**建议修复**:
```rust
// 显示修正后的代码
## 🟡 建议:[标题]
**位置**:`src/file.rs:123`
**当前方法**:[代码当前的做法]
**建议**:[更好的方法]
**好处**:
- [好处 1]
- [好处 2]
## 💡 细节建议:[标题]
**位置**:`src/file.rs:200`
**观察**:[小的改进点]
**为什么重要**:[可选解释]
| 问题 | 模式 | 修复 |
|---|---|---|
| 缺少 unwrap 上下文 | .unwrap() | .expect("描述性消息") 或适当的错误处理 |
| 克隆而非借用 | .clone() | 使用 &T 引用 |
| 阻塞异步运行时 | std::thread::sleep | tokio::time::sleep |
| SQL 注入风险 | format!("WHERE = {}", val) | 使用 ? 参数绑定 |
| N+1 查询 | 循环内包含查询 | 使用 JOIN 或批量查询 |
| 问题 | 模式 | 修复 |
|---|---|---|
| 控制台日志 | console.log() | 使用 message 组件 |
| 类型断言 | as any | 使用正确的类型 |
| 缺少依赖项 | useEffect(fn, []) | 添加所有依赖项 |
| 条件中的 Hook | if (condition) { useState() } | 移到顶层 |
| Key 属性问题 | key={index} | 使用唯一 ID |
# 运行所有自动化检查
cargo test --all
cargo clippy -- -D warnings
cargo fmt --check
npm test
npm run lint
npm run type-check
# 审查变更
git diff main...feature-branch
# 查看特定文件变更
git diff main..feature-branch -- src/file.rs
# 检查提交历史
git log --oneline main..feature-branch
# 运行测试
cargo test
npm test
# 检查格式
cargo fmt --check
npm run lint
后端 (Rust):
- [ ] Tauri 命令属性正确
- [ ] 错误处理全面
- [ ] SQL 查询安全且优化
- [ ] 性能考虑已解决
- [ ] 异步上下文中没有阻塞调用
前端 (React):
- [ ] TypeScript 类型正确
- [ ] Hooks 使用正确
- [ ] 没有 console.log
- [ ] 使用 message 进行错误处理
- [ ] 性能优化
集成:
- [ ] 类型安全的命令调用
- [ ] 适当的错误处理
- [ ] 命名一致
- [ ] specta 类型已生成
测试:
- [ ] 存在单元测试
- [ ] 覆盖边界情况
- [ ] 如果需要,存在集成测试
- [ ] 测试通过
文档:
- [ ] 公共 API 已记录
- [ ] 复杂逻辑已解释
- [ ] README 已更新
在以下情况下激活此技能:
每周安装次数
1
仓库
首次出现
今天
安全审计
安装于
zencoder1
amp1
cline1
openclaw1
opencode1
cursor1
Tailwind CSS v4 + shadcn/ui 生产级技术栈配置指南与最佳实践
2,600 周安装