Become a sponsor

概述
防重复提交是保障数据一致性的重要措施。通过前端防抖和后端唯一性校验双重保护,防止用户重复点击导致的数据重复提交。
ElementPlus 的按钮组件支持 loading 属性,请求期间禁用按钮:
<template>
<el-button
type="primary"
:loading="submitting"
@click="handleSubmit"
>
提交
</el-button>
</template>
<script setup>
const submitting = ref(false);
async function handleSubmit() {
submitting.value = true;
try {
await exampleAdd(formData.value);
ElMessage.success('添加成功');
} finally {
submitting.value = false;
}
}
</script>前端提供 useLockFn 钩子函数,实现请求级别的防重复提交:
import { useLockFn } from '@/utils/lock';
// 包装提交函数,防止重复点击
const handleSubmit = useLockFn(async () => {
await exampleAdd(formData.value);
ElMessage.success('添加成功');
});useLockFn 原理:
function useLockFn(fn: Function) {
let isLocked = false;
return async (...args: any[]) => {
if (isLocked) return;
isLocked = true;
try {
return await fn(...args);
} finally {
isLocked = false;
}
};
}通过 uniqueFields 属性声明唯一性校验字段:
class ExampleLogic extends BaseLogic
{
/**
* 写法一:单字段全局唯一
*
* @var array
*/
protected array $uniqueFields = ['name'];
/**
* 写法二:混合配置(全局唯一 + 分组唯一)
*
* @var array
*/
protected array $uniqueFields = [
'name',
['code', 'pid'],
];
}BaseLogic 在 add/update 时自动校验,重复则抛出异常:
// BaseLogic::checkUnique()
protected function checkUnique(array $data, ?int $excludeId = null): void
{
foreach ($this->uniqueFields as $rule) {
if (is_string($rule)) {
$field = $rule;
$groupField = null;
} else {
$field = $rule[0];
$groupField = $rule[1] ?? null;
}
if (!isset($data[$field]) || $data[$field] === '') {
continue;
}
$query = $this->getModel()->where($field, $data[$field]);
if ($groupField && isset($data[$groupField])) {
$query = $query->where($groupField, $data[$groupField]);
}
if ($excludeId !== null) {
$query = $query->where('id', '<>', $excludeId);
}
if ($query->find()) {
$label = $this->getFieldLabel($field);
throw new \Exception($label . '已存在');
}
}
}软删除场景下,唯一索引需要特殊处理:
-- MySQL:唯一索引包含 is_delete 字段
ALTER TABLE think_example ADD UNIQUE INDEX uk_name (name, is_delete);1. 前端防抖:按钮 loading 状态控制,防止用户重复点击
2. 后端校验:Logic uniqueFields + 数据库唯一索引,双重保障
3. 幂等设计:相同请求多次执行结果一致
4. 错误提示:重复提交时返回明确的错误提示("xxx已存在")