Files
shanxia2.0/docs/superpowers/plans/2026-06-29-creator-only-delete.md
T
2026-06-29 11:15:39 +08:00

14 KiB
Raw Blame History

仅创建人可删除 — 删除接口 / 页面对照表与分阶段改造方案

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: 业务数据删除时,仅允许 create_by === 当前用户(super_admin 可例外);后端强制校验,前端按创建人显隐/禁用删除按钮。

Architecture: 后端新增统一 assert_row_deletable_by_creator(),在各模块 soft_delete / delete_* 入口调用;前端新增 canDeleteByCreator() 工具与可选 CreatorDeleteButton 包装;列表批量删除过滤非本人数据并提示。系统管理类主数据默认不纳入本规则(见 §4)。

Tech Stack: FastAPI + SQLAlchemy(backend)、Vue 3 + Element Plus(web-admin)

默认产品假设(实施前需客户签字确认):

项 默认
超管 super_admin 可删除任意业务数据
系统管理 租户/用户/角色/菜单/部门/字典/站点/职位/流程定义/请假 — 不适用创建人规则
子表 跟进、联系人、开票信息、商机产品等 — 适用创建人规则
历史空 create_by 仅 super_admin 可删;普通用户不可删
比对字段 后端用 user_id(UUID);前端用 row.createBy,禁止用 realName

1. 统计摘要

类别 后端删除接口(约) 前端含「删除」页面(约)
CRM 业务 18 22
PL 物流 8 9
DB 地磅 3 2
BX 报销 5 5
系统管理 11 11
UI 本地删除(不改) — ~8 组件/页
合计(业务范围内) 34 38

2. 需改造对照表(业务数据 — 纳入范围)

2.1 CRM

# 实体 后端接口 后端实现位置 前端 API 前端页面 / 入口 批量删除 现状
C01 线索 POST /web/crm/clue/delete crm.py → soft_delete_clue delClue crm/clue/index.vue 行删 否 仅 data_scope
C02 线索 同上 同上 delClue crm/clue/detailDrawer.vue 主删 — 无创建人校验
C03 线索跟进 POST /web/crm/clue/follow/delete delete_clue_follow delClueFollow detailDrawer.vue 跟进删 否 前端 canManageFollow(createBy);后端 data_scope
C04 客户 POST /web/crm/customer/delete soft_delete_customer fetchDeleteCustomer crm/customer/index.vue 否 无
C05 客户 同上 同上 同上 CustomerDetailDialog.vue 主删 — 无
C06 客户跟进 POST /web/crm/customer/follow/delete soft_delete_follow fetchDeleteCustomerFollow CustomerDetailDialog.vue 否 前端 realName+admin(脆弱)
C07 联系人 POST /web/crm/contact/delete soft_delete_contact fetchDeleteContact CustomerDetailDialog.vue、ContactList.vue 否 无
C08 开票信息 POST /web/crm/invoice-info/delete soft_delete_invoice_info delInvoiceInfo InvoiceInfo.vue 否 无
C09 商机 POST /web/crm/opportunity/delete soft_delete_opportunities delOpportunity opportunity/index.vue 否 无
C10 商机 同上 同上 同上 OpportunityDetailDrawer.vue 主删 — 无
C11 商机跟进 POST /web/crm/opportunity/follow/delete soft_delete_opportunity_follow delOpportunityFollow OpportunityDetailDrawer.vue 否 无
C12 商机产品 POST /web/crm/opportunity/product/delete soft_delete_opportunity_products delOpportunityProduct 表单内(若有持久化删) 否 无
C13 报价 POST /web/crm/quote/delete soft_delete_quotes delQuote quote/index.vue 是 无
C14 报价 同上 同上 同上 quote/detail.vue、QuoteDetailDialog.vue — 无
C15 报价产品 POST /web/crm/quote/product/delete soft_delete_quote_products delQuoteProduct 已保存明细删(若有) 否 无;表单内行删见 §3
C16 合同 DELETE /web/crm/contract/{ids} soft_delete_contracts delContract contract/index.vue 是 无
C17 合同 同上 同上 同上 contract/detail.vue、ContractDetailDialog.vue — 无
C18 合同变更 DELETE /web/crm/contract/change/{ids} soft_delete_contract_changes delChange contract/change/index.vue 是 无
C19 合同模板 DELETE /web/crm/contract/template/{ids} soft_delete_contract_templates delTemplate contract/template/index.vue 是 无
C20 产品 POST /web/crm/products/delete soft_delete_product fetchDeleteProduct crm/product/index.vue 是 无
C21 产品分类 POST /web/crm/product-categories/delete soft_delete_category fetchDeleteProductCategory crm/product-category/index.vue 否 无
C22 公海规则 POST /web/crm/customer/pool/rule/delete delete_pool_rules fetchDeletePoolRule customer/pool/RuleIndex.vue 否 无
C23 供应商信息 POST /web/crm/supplierInfo/delete soft_delete_supplier_info delSupplierInfo 暂无独立列表删入口 — 预留后端

2.2 PL 物流

# 实体 后端接口 后端实现位置 前端 API 前端页面 批量 现状
P01 承运商 DELETE /transport/carrier/{id} pl/base_data.py carrierApi.delete pl/carrier/index.vue 否 data_scope
P02 车辆 DELETE /transport/vehicle/{id} 同上 vehicleApi.delete pl/vehicle/index.vue 否 data_scope
P03 自有车辆 同上 同上 同上 pl/self-vehicle/index.vue 否 data_scope
P04 人员 DELETE /transport/personnel/{id} 同上 personnelApi.delete pl/personnel/index.vue 否 data_scope
P05 司机 DELETE /transport/driver/{id} 同上 driverApi.delete pl/driver/index.vue 否 data_scope
P06 车辆-司机关联 DELETE /transport/vehicle-driver/{id} 同上 (内嵌于车辆/人员维护) 车辆/人员表单内 否 data_scope
P07 运输计划 DELETE /transport/plan/{id} pl/plan.py planApi.delete pl/plan/index.vue 否 data_scope
P08 运费结算单 DELETE /transport/freight/{id} pl/freight.py → delete_draft_settlement freightApi.delete pl/freight/SettlementBillPanel.vue 否 仅草稿;无 create_by 校验

2.3 DB 地磅

# 实体 后端接口 后端实现位置 前端 API 前端页面 现状
D01 库存记录 DELETE /inventory/{id} db/inventory.py inventoryApi.delete db/inventory/index.vue 前端日期规则;后端 data_scope
D02 地磅计划 DELETE /plans/{id} db/plans.py plansApi.delete db/plans/index.vue data_scope
D03 过磅记录 DELETE /weighing/{id} db/weighing.py weighingApi.delete 公开页若有 data_scope

2.4 BX 报销

# 实体 后端接口 后端实现位置 前端 API 前端页面 现状
B01 报销申请 DELETE /reimburses/{id} bx/reimburse.py → ReimburseService.soft_delete reimburseApi.delete bx/reimburse/apply/index.vue data_scope
B02 预支申请 DELETE /advances/{id} bx/advance.py advanceApi.delete bx/advance/apply/index.vue data_scope
B03 费用项 DELETE /expense-items/{id} bx/expense_item.py expenseItemApi.delete bx/expense-item/index.vue data_scope
B04 附件 DELETE /attachments/{id} bx/attachment.py attachmentApi.delete BxAttachmentUpload 等 随主单;删附件也需创建人
B05 BX 工作流配置 DELETE /workflows/{id} bx/workflow.py workflowApi.delete `bx/workflow/reimburse advance/index.vue`

3. 不纳入改造(UI 本地 / 非持久化删除)

页面 / 组件 说明
QuoteFormPanel.vue handleDeleteProducts / handleRemoveProduct 编辑表单内未提交行,非 API 删库
contract/form.vue 行项删除 同上
ContractAttachmentPanel.vue 表单附件列表本地 splice
attachment-upload-field、BxAttachmentUpload 未保存附件卡片
FlowDesigner.vue 流程设计器节点/连线
system/user/detail.vue 地址删除 本地 mock 数组
art-global-search 搜索历史 本地 storage

4. 默认排除(系统管理 — 待客户确认是否纳入)

# 实体 后端接口 前端页面
S01 租户 DELETE /web/admin/tenants/{id} system/tenant/index.vue
S02 用户 DELETE /web/admin/users/{id} system/user/index.vue
S03 角色 DELETE /web/admin/role-management/{id} system/role/index.vue
S04 菜单 DELETE /web/admin/menus/{id} system/menu/index.vue
S05 部门 DELETE /web/admin/depts/{id} system/dept/index.vue
S06 字典类型/数据 `DELETE .../dict-types dict-data/{id}`
S07 站点 DELETE /web/admin/sites/{id} system/site/index.vue
S08 职位 DELETE /web/admin/posts/{id} system/post/index.vue
S09 流程定义 DELETE /web/admin/workflow/defs/{id} system/workflow/process/index.vue
S10 请假 DELETE /web/admin/leave/{id} system/leave/index.vue

5. 分阶段改造方案

Phase 0 — 基础设施(必须先做)

后端

  • 新建 backend/app/core/delete_guard.py
    • assert_row_deletable_by_creator(row, user_info, *, message="仅创建人可删除")
    • assert_rows_deletable_by_creator(rows, user_info) — 批量时全量校验
    • super_admin bypass;create_by 为空时仅超管可删
  • 单元测试 backend/tests/test_delete_guard.py(创建人匹配 / 不匹配 / 超管 / 空 create_by)

前端

  • 新建 web-admin/src/utils/creator-delete.ts
    • getCurrentUserId() — 从 useUserStore().info 取 userId / id
    • canDeleteByCreator(row, currentUserId?) — 比对 row.createBy
    • filterDeletableRows(rows) — 批量删前过滤
    • CREATOR_DELETE_TIP = '仅创建人可删除'
  • 可选:web-admin/src/components/business/creator-delete-button/index.vue — 统一 disabled + tooltip

文档

  • OpenSpec 变更提案:openspec/changes/creator-only-delete/(permission + api conventions 各一条 Requirement)

Phase 1 — CRM 主实体(优先级最高)

后端(每个 soft_delete 入口加 assert)

  • C01–C02 线索 — soft_delete_clue
  • C04–C05 客户 — soft_delete_customer
  • C09–C10 商机 — soft_delete_opportunities
  • C13–C14 报价 — soft_delete_quotes
  • C16–C17 合同 — soft_delete_contracts
  • C18 合同变更 — soft_delete_contract_changes
  • C19 合同模板 — soft_delete_contract_templates

前端

  • 上表对应 10 个页面/抽屉:行删 / 工具栏删 v-if="canDeleteByCreator(row)"
  • 批量删(报价/合同/变更/模板):选中时过滤 + ElMessage.warning 提示跳过条数
  • 列表接口确认返回 createBy(缺则补 _row_to_dict)

验收

  • 用户 A 创建、用户 B(同部门、有删权限)调用 API 返回 403
  • 用户 A 可删自己的数据;超管可删任意

Phase 2 — CRM 子实体 + 主数据

后端

  • C03/C06–C08/C11–C12 跟进、联系人、开票、商机产品
  • C20–C22 产品、分类、公海规则
  • C23 供应商(仅后端,无 UI 也先加固)

前端

  • 替换 CustomerDetailDialog 跟进删:realName → canDeleteByCreator
  • 统一 clue/detailDrawer canManageFollow 改用公共 util
  • InvoiceInfo、ContactList、product、product-category、RuleIndex

Phase 3 — PL + DB

后端

  • P01–P08:delete_carrier/vehicle/personnel/driver/plan + delete_draft_settlement 加 create_by
  • P06 vehicle-driver 删关联
  • D01–D03 库存/计划/过磅

前端

  • PL 9 页 + DB 2 页按钮控制
  • db/inventory:保留现有日期规则,与创建人规则 AND 关系

Phase 4 — BX 报销

后端

  • B01–B04:在 BxCrudService.soft_delete 或各 Service 包装层加 create_by(注意 BX 部分历史 create_by 存 name 的脏数据,需迁移或兼容比对)

前端

  • bx/reimburse/apply、bx/advance/apply、bx/expense-item、附件组件

备注: B05 BX 工作流配置默认跳过;若客户要求纳入,单独开 Phase 4b。


Phase 5 — 系统管理(可选,需客户确认)

  • 若确认纳入:S01–S10 后端 + 11 个 system 页面
  • 若不纳入:在帮助文档注明「系统管理不受创建人删除限制」

6. 批量删除统一行为

场景 前端 后端
选中含他人数据 禁用批量删或只提交本人 id 并提示 对每条 assert;部分失败返回明细
选中全无 createBy 普通用户禁用;超管可删 空 create_by 仅超管
混合选中 推荐:过滤后仅删本人,Message 汇总 事务:建议全失败或逐条(与 CRM 现有 delClue 部分失败风格对齐)

7. 实施顺序与估时

Phase 范围 后端 前端 估时
0 基础设施 0.5d 0.5d 1d
1 CRM 主实体 1d 1.5d 2.5d
2 CRM 子实体 1d 1d 2d
3 PL + DB 1d 1d 2d
4 BX 1d 0.5d 1.5d
5 系统管理(可选) 1d 1d 2d

建议迭代: 每 Phase 独立 PR,先后端再前端,每模块手工回归 2 用户(创建人 / 非创建人)。


8. 下一步

  1. 客户确认 § 默认产品假设 + §4 系统管理是否纳入
  2. 执行 Phase 0 并合入主分支
  3. 按 Phase 1 → 4 逐步交付,每阶段更新本文件 checkbox