# CRM 开票导入 - 前端联调方案 > 需求:开票管理列表增加「导入」按钮(位于「新增开票申请」与「导出」之间),用于按模板批量导入开票记录。 > 参考实现:合同列表的导入弹窗(`views/crm/contract/modules/import-form.vue`),开票导入与其交互一致。 ## 涉及页面 - 修改:`views/crm/invoice/index.vue`(开票列表工具栏) - 新增:导入弹窗组件(建议 `views/crm/invoice/modules/import-form.vue`) - 修改:`src/api/crm/invoice/index.ts`(新增 2 个接口) ## 业务流程与数据带入 1. 合同(已审核通过)-> 开票导入:模板中填写「合同编号」,后端按编号匹配合同,**客户自动取合同所属客户**,无需在模板中填写客户 2. 导入成功 -> 开票列表:新增的开票为「未提交」状态,可在列表中继续编辑、上传发票附件、提交审批 3. 导入的负责人 = 当前登录用户(同合同导入),导入后当前用户即可在「我负责的」下看到 ## API | 方法 | 路径 | 说明 | |------|------|------| | GET | `/crm/invoice/get-import-template` | 下载导入模板(返回 xls 文件流) | | POST | `/crm/invoice/import` | 导入开票(multipart 上传 Excel) | **权限码:** 两个接口均要求 `crm:invoice:import`(菜单已新增:营销管理 -> 开票管理 -> 开票导入,并已授予开票管理现有角色)。 **请求参数(POST /crm/invoice/import):** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | file | MultipartFile | 是 | 仅支持 xls、xlsx | **模板列(下载的模板已含表头与一行示例):** | 列名 | 必填 | 说明 | |------|------|------| | 开票编号 | 否 | 留空则系统自动生成(KP+日期+6位序号);填写时不可与系统中已有开票编号重复 | | 合同编号 | 是 | 需与系统中**已审核通过**的合同编号一致,客户由合同自动带入 | | 发票类型 | 是 | 填写字典 `crm_invoice_type` 的名称:增值税专用发票 / 增值税普通发票 / 电子发票 | | 发票号码 | 否 | 发票票面号码 | | 发票抬头 | 否 | 发票抬头 | | 开票金额(元) | 是 | 需大于 0,且不超过该合同剩余可开票金额 | | 开票日期 | 否 | 格式 `2026-01-01 10:00:00` 或 `2026-01-01`;留空取当前时间 | | 备注 | 否 | 备注 | **响应:** ```json { "code": 0, "data": { "createList": ["KP20260924000001", "KP20260924000002"], "failureList": { "第 4 行": "合同编号不存在:HT9999。请先在「CRM 合同管理」中创建或导入该合同(编号需与模板完全一致),或修改模板中的合同编号后重新导入" } } } ``` | 字段 | 类型 | 说明 | |------|------|------| | createList | String[] | 导入成功的开票编号数组 | | failureList | Map | 导入失败集合:key 为「发票号码 xxx」或「第 N 行」(N 为 Excel 行号,含表头),value 为失败原因 | ## 字段展示规则 | 字段 | 展示位置 | 说明 | |------|----------|------| | 导入按钮 | 开票列表工具栏 | 位置在「新增开票申请」与「导出」之间;权限码 `crm:invoice:import` | | 下载导入模板按钮 | 导入弹窗左下角 | 同合同导入弹窗的 `prepend-footer` 位置 | | 新增条数 | 导入弹窗结果区 | 取 `createList.length`,文案如「新增:N 条」 | | 失败明细 | 导入弹窗结果区 | 遍历 `failureList`,逐条展示「key:value」,可滚动 | | 导入模板说明 | 导入弹窗内灰色提示区 | 必填列:合同编号、发票类型、开票金额;合同必须为「审核通过」;负责人 = 当前登录用户;状态为「未提交」 | ## 业务规则说明 | 场景 | 规则 | |------|------| | 合同状态 | 只有「审核通过」的合同才能导入开票;未提交/审批中/不通过的合同该行导入失败 | | 开票金额上限 | 单行金额不得超过「合同金额 − 已开票(审批中 + 审核通过)」的剩余额度,超出则该行失败 | | 重复编号 | 模板中填写的开票编号在系统中已存在时该行失败 | | 部分成功 | 逐行导入,失败行不影响成功行(同一文件内不会整体回滚) | | 数据权限 | 导入的开票负责人 = 当前登录用户,自动创建数据权限,无需前端处理 | | 与「新建开票申请」的差异 | 导入不产生附件;导入的开票默认「未提交」,需在列表中编辑上传发票附件后再提交审批 | ## 注意事项 - 模板「发票类型」填**名称**(如 增值税专用发票),也兼容填数字(1/2/3);填错时失败原因会列出可选项 - 导入弹窗的进度条/结果区交互可直接复用合同导入的实现(`import-form.vue`) - 前端按钮的 `auth` 需使用新的权限码 `crm:invoice:import`;该菜单权限已授予角色 2/155/160/161/162,其余自建角色需在「角色管理」中勾选「开票导入」后再使用 - 空行会被自动跳过,不算失败