views/crm/invoice/index.vue(开票列表)、views/crm/invoice/modules/form.vue(开票表单)、views/crm/invoice/detail/index.vue(开票详情)src/api/crm/invoice/index.ts(开票接口)views/crm/receivable/modules/form.vue(回款表单增加「先开票后回款」提示与校验)后端菜单已新增「营销管理 -> 开票管理」(component =
crm/invoice/index),前端只需创建对应目录与页面组件。
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /crm/invoice/create |
创建开票 |
| PUT | /crm/invoice/update |
更新开票(仅草稿/审批中) |
| DELETE | /crm/invoice/delete |
删除开票(审批通过不可删) |
| GET | /crm/invoice/get |
获得开票详情(含附件列表) |
| GET | /crm/invoice/page |
获得开票分页 |
| GET | /crm/invoice/page-by-customer |
基于客户的开票分页 |
| GET | /crm/invoice/export-excel |
导出开票 Excel |
| PUT | /crm/invoice/submit |
提交开票审批 |
| GET | /crm/invoice/audit-count |
待审核开票数量 |
创建/更新请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | Long | 否 | 更新时必填 |
| contractId | Long | 是 | 合同编号,选择合同后客户自动带入 |
| ownerUserId | Long | 否 | 负责人,默认当前用户 |
| invoiceType | Integer | 是 | 发票类型,字典 crm_invoice_type(1专用 2普通 3电子) |
| invoiceNo | String | 否 | 发票号码 |
| invoiceTitle | String | 否 | 发票抬头 |
| price | BigDecimal | 是 | 开票金额(元) |
| invoiceTime | LocalDateTime | 是 | 开票日期 |
| remark | String | 否 | 备注 |
| blobIds | Long[] | 否 | 发票附件 BlobId 列表 |
响应字段新增:
| 字段 | 类型 | 说明 |
|---|---|---|
| no | String | 开票编号(KP+日期+序号,保存时后端生成) |
| customerId / customerName | Long / String | 客户 |
| contract | CrmContractRespVO | 合同信息 |
| ownerUserName / ownerUserDeptName | String | 负责人/部门 |
| auditStatus | Integer | 审批状态(字典 crm_audit_status) |
| attachmentList | StorageBlobRespDTO[] | 发票附件列表 |
| processInstanceId | String | 工作流编号 |
响应示例:
{
"code": 0,
"data": {
"id": 1,
"no": "KP20260810000001",
"contractId": 100,
"contract": { "id": 100, "no": "HT2026...", "name": "..." },
"customerId": 200,
"customerName": "XX科技",
"invoiceType": 1,
"invoiceNo": "02564178",
"invoiceTitle": "XX科技有限公司",
"price": 9000.00,
"invoiceTime": "2026-08-10",
"auditStatus": 0,
"attachmentList": [{ "id": 1, "url": "...", "name": "发票.pdf" }]
}
}
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /system/storage-blob/upload |
上传发票文件,获得 blobId |
| POST | /system/storage-attachment/bind |
绑定附件到开票(recordType=crm_invoice、recordId=开票id) |
| GET | /system/storage-attachment/list |
查询开票附件列表 |
| DELETE | /system/storage-attachment/delete |
删除附件 |
上传与保存分离:表单先选文件上传拿到
blobId,随创建/更新接口一起提交blobIds;后端绑定。详情接口返回的attachmentList可直接展示/预览。
| 字段 | 展示位置 | 说明 |
|---|---|---|
| no 开票编号 | 列表、详情 | 跳转详情 |
| customerName 客户 | 列表、详情 | 跳转客户详情 |
| contract 合同 | 列表、详情 | 跳转合同详情 |
| invoiceType 发票类型 | 列表、详情 | 字典展示 |
| invoiceNo 发票号码 | 列表、详情 | - |
| price 开票金额 | 列表、详情 | 金额格式化 |
| invoiceTime 开票日期 | 列表、详情 | 日期格式化 |
| auditStatus 审批状态 | 列表、详情 | 字典 crm_audit_status |
| attachmentList 发票附件 | 详情 | 附件列表,可预览/下载 |
| ownerUserName 负责人 | 列表 | - |
| remark 备注 | 列表、详情 | - |
| 场景 | 规则 |
|---|---|
| 创建回款 | 后端校验:同合同「审批通过且已上传发票附件」的累计开票金额 >= 累计回款金额(含本次),否则报错「合同累计开票金额不足,目前可回款 X 元」 |
| 开票金额 | 后端校验:开票金额不能超过合同金额减去已审批通过的开票金额 |
| 开票编辑 | 仅草稿、审批中可编辑;客户、合同、负责人不可修改 |
| 开票删除 | 审批通过后不可删除 |
| 开票审批 | 提交后走 BPM 流程(key=crm-invoice-audit),审批通过才生效 |
| 待办 | 后端 audit-count 可用于待办红点 |
crm_invoice_type 后端已配置,前端需在常量/字典中注册(1增值税专用 2增值税普通 3电子)crm:invoice:*)分配给相应角色/system/storage-* 接口,recordType 固定为 crm_invoice,禁止在业务表新增文件地址字段