编辑 | blame | 历史 | 原始文档

售后工单模块 - 前端联调方案

涉及页面(全部新建)

页面 路由建议 说明
售后工单列表 /aftersales/ticket 工单列表、搜索、状态筛选
售后工单详情/编辑 /aftersales/ticket/detail?id=:id 新建/编辑工单、查看详情
退货申请列表 /aftersales/return 退货申请列表、搜索
退货申请详情 /aftersales/return/detail?id=:id 退货详情、审核操作

业务流程与数据带入

流程一:一般问题工单

创建工单 → 分配处理人 → 问题判定(一般问题)→ 处理 → 完结 → 关闭

流程二:退货问题工单

创建工单 → 分配处理人 → 问题判定(退货问题)
  → 创建退货申请 → 销售审核 → [MES退货流程自动执行] → 退款/换货完成 → 完结 → 关闭

流程三:维修问题工单

创建工单 → 分配处理人 → 问题判定(维修问题)
  → 创建维修记录 → 维修完成 → 完结 → 关闭

数据带入关系

步骤 来源 带入字段
创建退货申请 工单详情 ticketIdcustomerIdsaleOrderId、工单明细行(ticketItemIditemIditemCodeitemName
退货申请审批 退货申请 id(通过 URL 参数或按钮传入)

重点说明:
- 创建退货申请时,从工单详情页的明细行中筛选 needReturn = true 的行作为退货明细
- 退货明细中的 ticketItemId 必须对应工单明细行的 id
- 物料信息(itemIditemCodeitemName)从工单明细行带入,不允许修改
- 销售单价(unitPrice)需要从销售订单行查询获取,前端可通过已有的 ERP 销售订单接口查询


API 说明

一、售后工单

方法 路径 权限 说明
POST /aftersales/ticket/create aftersales:ticket:create 创建工单
PUT /aftersales/ticket/update aftersales:ticket:update 更新工单(仅草稿状态可更新)
DELETE /aftersales/ticket/delete aftersales:ticket:delete 删除工单(仅草稿/已取消状态可删除)
GET /aftersales/ticket/get aftersales:ticket:query 获取工单详情
GET /aftersales/ticket/page aftersales:ticket:query 分页查询工单
POST /aftersales/ticket/assign aftersales:ticket:update 分配处理人
POST /aftersales/ticket/classify aftersales:ticket:update 问题判定
PUT /aftersales/ticket/resolve aftersales:ticket:update 完结工单
PUT /aftersales/ticket/close aftersales:ticket:update 关闭工单
PUT /aftersales/ticket/cancel aftersales:ticket:update 取消工单

1.1 创建工单 POST /aftersales/ticket/create

请求参数:

参数 类型 必填 说明
name String 工单主题
customerId Long 客户编号
contactId Long 联系人编号
saleOrderId Long 销售订单编号
saleOrderNo String 销售订单号(冗余,与 saleOrderId 配套传入)
contractId Long 合同编号
issueDescription String 问题描述
remark String 备注
items List<Item> 明细行列表

Item 结构:

参数 类型 必填 说明
saleOrderItemId Long 销售订单行编号
itemId Long MDM 物料编号
itemCode String 物料编码
itemName String 物料名称
batchId Long 生产批次编号
batchCode String 生产批次号
saleQuantity BigDecimal 销售数量
returnQuantity BigDecimal 退货数量
needRepair Boolean 是否需要维修
needReturn Boolean 是否需要退货
remark String 备注

请求示例:
json { "name": "产品外观缺陷投诉", "customerId": 1, "contactId": 2, "saleOrderId": 100, "saleOrderNo": "SO202401010001", "contractId": 50, "issueDescription": "收到货后发现产品表面有明显划痕", "remark": "客户要求尽快处理", "items": [ { "saleOrderItemId": 10, "itemId": 200, "itemCode": "MAT-001", "itemName": "电子元器件", "batchId": 5, "batchCode": "BATCH-2024-001", "saleQuantity": 100.000, "returnQuantity": 10.000, "needRepair": false, "needReturn": true, "remark": "外观缺陷" } ] }

响应: { "code": 0, "data": 1 } — data 为新建工单 ID

1.2 更新工单 PUT /aftersales/ticket/update

请求参数与创建相同,额外需要 id 字段。仅草稿状态可更新。

1.3 删除工单 DELETE /aftersales/ticket/delete

参数 类型 必填 说明
id Long 工单编号(Query 参数)

响应: { "code": 0, "data": true }

1.4 获取工单详情 GET /aftersales/ticket/get

参数 类型 必填 说明
id Long 工单编号(Query 参数)

响应字段:

字段 类型 说明
id Long 工单编号
no String 工单单号(格式:AS + yyyyMMdd + 6位序号)
name String 工单主题
customerId Long 客户编号
customerName String 客户名称
contactId Long 联系人编号
contactName String 联系人名称
saleOrderId Long 销售订单编号
saleOrderNo String 销售订单号
contractId Long 合同编号
issueType Integer 问题类型:1-一般问题 2-维修问题 3-退货问题
issueCategory String 问题分类
issueDescription String 问题描述
severityLevel Integer 严重程度:0-轻微 1-一般 2-严重 3-致命
status Integer 状态(见状态枚举)
ownerUserId Long 负责人用户编号
ownerUserName String 负责人名称
handlerUserId Long 处理人用户编号
handlerUserName String 处理人名称
processInstanceId String BPM 工作流实例编号
returnId Long 关联退货申请编号
repairId Long 关联维修记录编号
resolvedTime DateTime 解决时间
closedTime DateTime 关闭时间
remark String 备注
creator String 创建者
createTime DateTime 创建时间
updater String 更新者
updateTime DateTime 更新时间
items List<Item> 明细行列表

响应示例:
json { "code": 0, "data": { "id": 1, "no": "AS20260730000001", "name": "产品外观缺陷投诉", "customerId": 1, "customerName": "XX科技有限公司", "contactId": 2, "contactName": "张三", "saleOrderId": 100, "saleOrderNo": "SO202401010001", "contractId": 50, "issueType": 3, "issueCategory": "外观缺陷", "issueDescription": "收到货后发现产品表面有明显划痕", "severityLevel": 1, "status": 30, "ownerUserId": 1, "ownerUserName": "管理员", "handlerUserId": 2, "handlerUserName": "售后专员", "returnId": 1, "items": [ { "id": 1, "ticketId": 1, "saleOrderItemId": 10, "itemId": 200, "itemCode": "MAT-001", "itemName": "电子元器件", "batchId": 5, "batchCode": "BATCH-2024-001", "saleQuantity": 100.000, "returnQuantity": 10.000, "needRepair": false, "needReturn": true } ] } }

1.5 分页查询工单 GET /aftersales/ticket/page

参数 类型 必填 说明
pageNo Integer 页码,默认 1
pageSize Integer 每页大小,默认 10
no String 工单单号
name String 工单主题
customerId Long 客户编号
saleOrderId Long 销售订单编号
status Integer 工单状态
issueType Integer 问题类型
sceneType Integer 场景类型:1-我负责的 2-我参与的 3-下属负责的 4-全部

响应:
json { "code": 0, "data": { "list": [ /* AfterSaleTicketRespVO 数组 */ ], "total": 100 } }

注意: 分页列表响应中的每条记录结构与详情接口一致(含 items 和关联名称字段),但列表场景下 items 可为空。

1.6 分配处理人 POST /aftersales/ticket/assign

参数 类型 必填 说明
id Long 工单编号(Query 参数)
handlerUserId Long 处理人用户编号(Query 参数)

业务规则: 仅草稿、处理中状态可分配。分配后状态自动变为"处理中"。

1.7 问题判定 POST /aftersales/ticket/classify

参数 类型 必填 说明
id Long 工单编号(Query 参数)
issueType Integer 问题类型:1-一般问题 2-维修问题 3-退货问题
issueCategory String 问题分类(如"外观缺陷"、"功能故障"等)
severityLevel Integer 严重程度:0-轻微 1-一般 2-严重 3-致命

业务规则: 仅处理中状态可判定。判定为退货问题后,应引导用户创建退货申请。

1.8 完结工单 PUT /aftersales/ticket/resolve

参数 类型 必填 说明
id Long 工单编号(Query 参数)

业务规则: 仅处理中/待退货/待退款状态可完结。

1.9 关闭工单 PUT /aftersales/ticket/close

参数 类型 必填 说明
id Long 工单编号(Query 参数)

业务规则: 仅已完结状态可关闭。

1.10 取消工单 PUT /aftersales/ticket/cancel

参数 类型 必填 说明
id Long 工单编号(Query 参数)

业务规则: 仅草稿、处理中状态可取消。


二、售后退货申请

方法 路径 权限 说明
POST /aftersales/return/create aftersales:return:create 创建退货申请
PUT /aftersales/return/approve aftersales:return:approve 审核通过(触发 MES 退货单)
GET /aftersales/return/get aftersales:return:query 获取退货详情
GET /aftersales/return/page aftersales:return:query 分页查询退货申请

2.1 创建退货申请 POST /aftersales/return/create

请求参数:

参数 类型 必填 说明
ticketId Long 关联工单编号
customerId Long 客户编号(从工单带入)
saleOrderId Long 关联销售订单编号(从工单带入)
returnType Integer 退货类型:1-退款退货 2-换货 3-仅退款
returnReason String 退货原因
defectCategory String 缺陷分类
remark String 备注
items List<Item> 退货明细行列表

Item 结构:

参数 类型 必填 说明
ticketItemId Long 工单明细行编号(关联 after_sale_ticket_item.id)
itemId Long MDM 物料编号(从工单明细行带入)
itemCode String 物料编码
itemName String 物料名称
batchId Long 批次编号
batchCode String 批次号
returnQuantity BigDecimal 退货数量
unitPrice BigDecimal 销售单价(需从销售订单行查询获取)
returnPrice BigDecimal 退货金额(= returnQuantity × unitPrice)
remark String 备注

请求示例:
json { "ticketId": 1, "customerId": 1, "saleOrderId": 100, "returnType": 1, "returnReason": "产品外观缺陷", "defectCategory": "外观缺陷", "remark": "客户要求退货退款", "items": [ { "ticketItemId": 1, "itemId": 200, "itemCode": "MAT-001", "itemName": "电子元器件", "batchId": 5, "batchCode": "BATCH-2024-001", "returnQuantity": 10.000, "unitPrice": 100.00, "returnPrice": 1000.00 } ] }

响应: { "code": 0, "data": 1 } — data 为新建退货申请 ID

业务规则:
- 创建退货申请后,关联工单状态自动变为"待退货(30)"
- returnPrice 后端会自动计算(returnQuantity × unitPrice 求和),前端可不传

2.2 审核通过 PUT /aftersales/return/approve

参数 类型 必填 说明
id Long 退货申请编号(Query 参数)

业务规则:
- 仅草稿状态(0)可审核
- 审核通过后,后端自动调用 MES 创建销售退货单,状态变为"审核通过-已同步MES(20)"
- 后续 MES 退货流程(质检→入库→退款)由后端回调自动完成,前端无需操作

2.3 获取退货详情 GET /aftersales/return/get

参数 类型 必填 说明
id Long 退货申请编号(Query 参数)

响应字段(新增/重要字段):

字段 类型 说明
id Long 退货申请编号
no String 退货单号(格式:RT + yyyyMMdd + 6位序号)
ticketId Long 关联工单编号
customerId Long 客户编号
customerName String 客户名称
saleOrderId Long 销售订单编号
returnType Integer 退货类型
returnReason String 退货原因
defectCategory String 缺陷分类
totalReturnPrice BigDecimal 应退总金额
actualRefundPrice BigDecimal 实退金额
status Integer 状态(见退货状态枚举)
auditUserId Long 审核人
auditTime DateTime 审核时间
mesReturnId Long MES退货单编号
mesReturnCode String MES退货单号
qualityResult String 质检结论
qualityReportUrl String 质检报告附件URL
returnInboundTime DateTime 退货入库完成时间
refundTime DateTime 退款完成时间
items List<Item> 退货明细行

2.4 分页查询退货申请 GET /aftersales/return/page

参数 类型 必填 说明
pageNo Integer 页码
pageSize Integer 每页大小
no String 退货单号
ticketId Long 关联工单编号
customerId Long 客户编号
status Integer 退货状态
sceneType Integer 场景类型

枚举值速查

工单状态 (AfterSaleTicketStatusEnum)

名称 说明
0 草稿 可编辑、可删除、可取消
10 处理中 可分配、可判定、可取消
30 待退货 退货流程进行中
40 待退款/换货 等待退款或换货完成
50 已完结 可关闭
60 已关闭 终态
99 已取消 终态

问题类型 (AfterSaleIssueTypeEnum)

名称 后续操作
0 未判定 创建工单时的初始值
1 一般问题 直接处理→完结
2 维修问题 创建维修记录→维修完成→完结
3 退货问题 创建退货申请→审核→MES退货→完结

退货状态 (AfterSaleReturnStatusEnum)

名称 说明
0 草稿 可审核
10 销售审核中
20 审核通过-已同步MES 等待MES处理
30 检验中 MES质检进行中
40 检验完成 等待入库
50 已入库 等待退款
60 退款/换货完成
70 已关闭 终态
99 已取消 终态

退货类型

名称
1 退款退货
2 换货
3 仅退款

严重程度

名称 建议颜色
0 轻微 绿色
1 一般 蓝色
2 严重 橙色
3 致命 红色

场景类型 (sceneType)

名称 说明
1 我负责的 当前用户为负责人
2 我参与的 当前用户为处理人或被授权
3 下属负责的 下属为负责人
4 全部 管理员查看所有

字段展示规则

工单列表页

字段 展示位置 说明
no 列表 单号,可点击进入详情
name 列表 工单主题
customerName 列表 客户名称
saleOrderNo 列表 销售订单号
issueType 列表 问题类型,用标签区分颜色
severityLevel 列表 严重程度,用标签区分颜色
status 列表 状态,用标签区分颜色
ownerUserName 列表 负责人
handlerUserName 列表 处理人
createTime 列表 创建时间
搜索区 单号、主题、客户、订单、状态、问题类型
搜索区 场景类型 Tab:我负责的/我参与的/下属负责的/全部

工单详情页

字段 展示区域 说明
no 头部 单号
name 头部 工单主题
status 头部 状态标签 + 状态流转按钮
customerId / customerName 基本信息 客户选择器(创建时可选,创建后只读)
contactId / contactName 基本信息 联系人选择器
saleOrderId / saleOrderNo 基本信息 销售订单选择器
contractId 基本信息 合同选择器
issueType 基本信息 问题类型(判定后显示)
issueCategory 基本信息 问题分类(判定后显示)
issueDescription 基本信息 问题描述
severityLevel 基本信息 严重程度(判定后显示)
ownerUserId / ownerUserName 基本信息 负责人(创建时自动设为当前用户)
handlerUserId / handlerUserName 基本信息 处理人(分配后显示)
returnId 基本信息 关联退货申请(可点击跳转)
repairId 基本信息 关联维修记录(可点击跳转)
resolvedTime 基本信息 解决时间(完结后显示)
closedTime 基本信息 关闭时间(关闭后显示)
remark 基本信息 备注
items 明细表格 物料、批次、销售数量、退货数量、是否维修、是否退货
createTime / creator 底部信息 创建信息
updateTime / updater 底部信息 更新信息

退货申请列表页

字段 展示位置 说明
no 列表 退货单号
ticketId 列表 关联工单编号(可点击跳转)
customerName 列表 客户名称
returnType 列表 退货类型标签
totalReturnPrice 列表 应退总金额
actualRefundPrice 列表 实退金额
status 列表 状态标签
mesReturnCode 列表 MES退货单号
qualityResult 列表 质检结论
createTime 列表 创建时间

退货申请详情页

字段 展示区域 说明
no 头部 退货单号
status 头部 状态标签 + 审核按钮(草稿状态显示)
ticketId 基本信息 关联工单(可点击跳转)
customerName 基本信息 客户名称
saleOrderId 基本信息 销售订单
returnType 基本信息 退货类型
returnReason 基本信息 退货原因
defectCategory 基本信息 缺陷分类
totalReturnPrice 基本信息 应退总金额
actualRefundPrice 基本信息 实退金额
mesReturnId / mesReturnCode MES信息 MES退货单
qualityResult MES信息 质检结论
qualityReportUrl MES信息 质检报告链接
returnInboundTime MES信息 入库时间
refundTime 退款信息 退款时间
items 明细表格 物料、批次、退货数量、单价、退货金额
createTime / creator 底部信息 创建信息

业务规则说明

工单操作按钮显隐规则

操作 草稿(0) 处理中(10) 待退货(30) 待退款(40) 已完结(50) 已关闭(60) 已取消(99)
编辑
删除
分配处理人
问题判定
创建退货申请 ✅(判定为退货后)
完结
关闭
取消

退货申请操作按钮显隐规则

操作 草稿(0) 审核中(10) 已同步MES(20) 检验中(30) 检验完成(40) 已入库(50) 退款完成(60)
审核通过
查看详情

分页查询数据权限说明

  • sceneType=1(我负责的):显示当前用户为 ownerUserId 的工单 + 数据交接的工单
  • sceneType=2(我参与的):显示当前用户有读/写权限的工单
  • sceneType=3(下属负责的):显示当前用户的下属负责的工单
  • sceneType=4(全部):需要管理员权限(aftersales:admin

文件上传

售后模块使用统一的文件上传机制,不自行实现上传接口。

上传流程:
1. 调用 POST /system/storage-blob/upload 上传文件 → 获得 blobId
2. 调用 POST /system/storage-attachment/bind 绑定到业务记录

recordType 取值:

业务对象 recordType
售后工单 aftersales_ticket
售后退货申请 aftersales_return

查询附件: GET /system/storage-attachment/list?recordType=aftersales_ticket&recordId=1


注意事项

  1. 明细行更新策略:更新工单时,明细行采用"先删后增"策略,前端必须传入完整的明细行列表(包括未修改的行),否则会导致明细行丢失。
  2. 单号生成:工单单号(AS前缀)和退货单号(RT前缀)由后端自动生成,前端不需要传入。
  3. 状态流转:所有状态变更操作(分配、判定、完结、关闭、取消、审核)后端都会校验当前状态是否允许,前端应根据按钮显隐规则控制操作入口。
  4. 退货审核后自动同步 MES:审核通过退货申请后,后端自动调用 MES 创建销售退货单,后续 MES 流程(质检→入库→退款)由回调自动推进状态,前端只需轮询刷新查看最新状态。
  5. 数据带入:创建退货申请时,必须从工单详情页跳转并带入 ticketIdcustomerIdsaleOrderId 以及工单明细行中标记为"需要退货"的行。
  6. 权限控制:所有接口都有 @PreAuthorize 权限校验,前端菜单和按钮需要对应配置权限标识。
  7. 路由权限:需在 src/router/routes/modules/ 下新建 aftersales.ts 路由模块文件,并在菜单中注册"售后服务"一级菜单。
  8. API 模块:需在 src/api/ 下新建 aftersales/ 目录,创建 ticket.tsreturn.ts 两个 API 文件。