Become a sponsor

防重复提交
防重复提交是保障数据一致性的重要措施。通过前端防抖和后端唯一性校验双重保护,防止用户重复点击导致的数据重复提交。后端唯一性校验通过 Pydantic @field_validator 查询数据库实现。
前端提供 useLockFn 钩子函数,实现请求级别的防重复提交:
import { useLockFn } from '@/utils/lock'
// 包装提交函数,防止重复点击
const handleSubmit = useLockFn(async () => {
await axios.post('/api/v1/level/add', formData)
ElMessage.success('添加成功')
})useLockFn 原理:
function useLockFn(fn) {
let isLocked = false
return async (...args) => {
if (isLocked) return
isLocked = true
try {
return await fn(...args)
} finally {
isLocked = false
}
}
}ElementPlus 的按钮组件支持 loading 属性,请求期间禁用按钮:
<el-button
type="primary"
:loading="submitting"
@click="handleSubmit"
>
提交
</el-button>
<script setup>
const submitting = ref(false)
async function handleSubmit() {
submitting.value = true
try {
await axios.post('/api/v1/level/add', formData)
ElMessage.success('添加成功')
} finally {
submitting.value = false
}
}
</script>通过数据库唯一索引和 Pydantic 验证器保证数据唯一性:
class LevelForm(BaseForm):
name: str = Field(..., min_length=1, max_length=150)
@field_validator('name')
@classmethod
def check_unique_name(cls, v, info):
# 查询数据库校验唯一性
if level_repo.exists_by_field('name', v, exclude_id=info.data.get('id')):
raise ValueError('职级名称已存在')
return v软删除场景下,唯一索引需要特殊处理:
-- MySQL: 唯一索引包含 is_delete 字段
ALTER TABLE fastapi_level ADD UNIQUE INDEX uk_name (name, is_delete);
-- PostgreSQL: 部分唯一索引
CREATE UNIQUE INDEX uk_name ON fastapi_level (name) WHERE is_delete = 0;1. 前端防抖:useLockFn 或按钮 loading,防止用户重复点击
2. 后端校验:Pydantic 验证器 + 数据库唯一索引,双重保障
3. 幂等设计:相同请求多次执行结果一致
4. 错误提示:重复提交时返回明确的错误提示防重复提交方案具备以下特点:
1. 前端防抖:useLockFn 函数级防抖,按钮 loading 状态控制
2. 后端校验:Pydantic 验证器查询数据库校验唯一性
3. 数据库约束:唯一索引兜底,防止并发重复插入
4. 双重保护:前端防抖 + 后端校验,确保数据一致性
5. 用户体验:重复点击时按钮禁用,返回明确提示