Files
rxthinkcmf-wiki/RXThinkCMF_Laravel13_NaiveVue/zh/standards/deletion.md
T
2026-10-08 17:50:29 +08:00

163 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 12.4 数据删除规范
## 软删除约定
:::tip 核心原则
所有业务数据统一使用软删除机制,通过 `is_delete` 字段标记记录状态,不物理删除数据(`SoftDeletesByFlag` Trait + `SoftDeleteFlagScope` 全局范围,不使用 `deleted_at`)。
:::
| is_delete 值 | 含义 |
|--------------|------|
| `0` | 正常记录(默认值) |
| `1` | 已删除记录 |
所有查询方法自动过滤 `is_delete = 0`,业务层无需关心已删除数据。
## 单条删除
### URL 格式
```text
DELETE /api/{module}/delete/{id}
```
### Controller 示例
```php
#[OperationLog('案例演示-删除', OperationLog::TYPE_DELETE, '删除案例ID:{id}')]
#[Permission('sys:example:delete', '删除案例')]
public function delete(int $id): JsonResponse
{
return $this->_delete($this->exampleService, $id);
}
```
### 内部流程
```text
Controller::delete($id)
│
▼
Controller 基类::_delete($service, $id)
│
▼
Service::delete($id) → HasCrudOperations::doDelete($id)
│ (DB::transaction 包裹)
├─ beforeDelete($id) 钩子(抛异常可拦截,事务回滚)
│
├─ $model->find($id)
│ └─ 不存在 → return false
│
├─ $model->softDelete() → UPDATE SET is_delete = 1
│
└─ afterDelete($id) 钩子
```
## 批量删除
### 请求格式
```text
DELETE /api/{module}/batchDelete
Content-Type: application/json
{ "ids": [1, 2, 3] }
```
### Controller 示例
```php
#[OperationLog('案例演示-批量删除', OperationLog::TYPE_DELETE)]
#[Permission('sys:example:batchDelete', '批量删除案例')]
public function batchDelete(): JsonResponse
{
$ids = $this->getJsonBody()['ids'] ?? [];
return $this->_batchDelete($this->exampleService, $ids);
}
```
### 内部流程
```text
Controller::batchDelete()
│
▼
Controller 基类::_batchDelete($service, $ids)
│
├─ ids 为空 → 返回失败 "请选择要删除的数据"
│
▼
Service::batchDelete($ids) → HasCrudOperations::doBatchDelete($ids)
│ (DB::transaction 包裹)
├─ beforeBatchDelete($ids) 钩子(整体校验)
│
├─ 逐条 beforeDelete($id) 校验
│
├─ Model::batchSoftDelete($ids)
│ └─ UPDATE SET is_delete = 1 WHERE id IN (...)
│
└─ afterBatchDelete($ids) 钩子
```
:::info 权限码区别
单条删除权限为 `sys:{模块}:delete`,批量删除权限为 `sys:{模块}:batchDelete`(代码生成器创建菜单时分别生成),前端按钮需分别控制显隐。
:::
## 删除前校验(beforeDelete 钩子)
在 Service 中重写 `beforeDelete` 方法,抛异常可拦截删除(事务自动回滚):
```php
class DeptService extends BaseTenantService
{
protected function beforeDelete(int $id): void
{
// 检查是否有子级
$children = Dept::where('parent_id', $id)->where('is_delete', 0)->count();
if ($children > 0) {
throw new \Exception('存在子部门,不可删除');
}
// 检查是否被引用
$userCount = User::where('dept_id', $id)->where('is_delete', 0)->count();
if ($userCount > 0) {
throw new \Exception('该部门下有用户,不可删除');
}
}
}
```
可用钩子(均在 `HasCrudOperations` 中声明):`beforeDelete($id)`、`afterDelete($id)`、`beforeBatchDelete($ids)`、`afterBatchDelete($ids)`。
## 何时可物理删除
| 场景 | 方式 | 说明 |
|------|------|------|
| 日志数据清理 | 定时任务 | 通过「定时任务」模块(job 表)配置清理 N 天前的日志 |
| 临时数据 | 定时任务 | 清理过期的临时文件 |
| 其它 | 审批 | 需经过管理员审批 |
## 前端删除规范
### 单条删除
```vue
<el-popconfirm title="确认删除该记录?" @confirm="handleDelete(row.id)">
<template #reference>
<el-button type="danger" size="small">删除</el-button>
</template>
</el-popconfirm>
```
### 批量删除
```vue
<el-button
type="danger"
:disabled="!selectedIds.length"
@click="handleBatchDelete"
>
批量删除 ({{ selectedIds.length }})
</el-button>
```