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

ERP 采购申请功能 - 前端变更文档

概述

新增 ERP 采购申请功能,实现从需求部门发起采购需求到生成采购订单的完整流程管理。

重要说明:采购申请审批需要集成 BPM 工作流,必须先在 BPM 模块创建 purchase_request_approve 分类和对应的审批流程。


一、前置条件

BPM 流程配置

采购申请审批需要 BPM 流程支持,必须先完成以下配置:

  1. 创建采购申请审批分类:在 BPM 流程分类中创建 purchase_request_approve 分类
  2. 创建采购申请审批流程:在 BPM 流程模型中创建采购申请审批流程
  • 流程标识(Key)必须为erp-purchase-request-audit
  • 关联到 purchase_request_approve 分类
  • 发布并激活流程

执行 SQL
sql -- 创建 BPM 采购申请审批分类 INSERT INTO bpm_category (id, name, code, description, status, sort, creator, create_time, updater, update_time, deleted) VALUES (101, '采购申请审批', 'purchase_request_approve', '采购申请审批流程分类', 0, 11, '1', NOW(), '1', NOW(), 0);

校验逻辑
- 提交采购申请时,系统会校验 BPM 采购申请审批分类是否存在
- 如果分类不存在,会抛出异常:采购申请审批分类不存在,请先在BPM模块创建采购申请审批流程分类
- 如果流程标识为 erp-purchase-request-audit 的流程未发布或未激活,会抛出异常:采购申请审批流程未发布或未激活,请先创建流程标识为[erp-purchase-request-audit]的流程模型并发布


二、涉及页面

  • /erp/purchase/request/index - 采购申请列表
  • /erp/purchase/request/form - 采购申请表单(新增/编辑)
  • /erp/purchase/request/detail - 采购申请详情

三、功能清单

序号 功能 说明
1 新增采购申请 创建草稿状态的采购申请
2 编辑采购申请 修改草稿状态的采购申请
3 删除采购申请 删除草稿状态的采购申请
4 提交审批 提交 BPM 流程审批
5 生成采购订单 审批通过后生成采购订单
6 导出 Excel 导出采购申请列表

四、API 接口

方法 路径 说明
POST /erp/purchase-request/create 创建采购申请
PUT /erp/purchase-request/update 更新采购申请
PUT /erp/purchase-request/submit 提交采购申请审批
DELETE /erp/purchase-request/delete 删除采购申请
GET /erp/purchase-request/get 获得采购申请详情
GET /erp/purchase-request/page 获得采购申请分页
GET /erp/purchase-request/export-excel 导出采购申请 Excel
POST /erp/purchase-request/generate-order 生成采购订单
GET /erp/purchase-request/approve-process-list 获取审批流程列表

文件上传:使用通用接口 POST /infra/file/upload,参数 file + directory=purchase-request,返回文件 URL。详见 docs/file_upload_guide.md

4.1 创建采购申请

请求参数:

参数 类型 必填 说明
requestTime DateTime 申请时间
requestReason String 申请理由
supplierId Long 供应商编号(可选)
discountPercent BigDecimal 优惠率,百分比
fileUrl String 附件地址
remark String 备注
items List 申请明细列表

items 明细参数:

参数 类型 必填 说明
productId Long 产品编号
productUnitId Long 产品单位编号
productPrice BigDecimal 产品单价(参考价)
count BigDecimal 数量
taxPercent BigDecimal 税率,百分比
demandTime Date 需求日期
remark String 备注

响应: { "code": 0, "data": 1001, "msg": "操作成功" }

4.2 提交采购申请审批

请求参数:

参数 类型 必填 说明
id Long 采购申请编号
processDefinitionKey String 流程定义 Key(用户从流程列表中选择)

响应: { "code": 0, "msg": "操作成功" }

流程选择:提交审批前,需先调用 /erp/purchase-request/approve-process-list 获取可选流程列表,让用户选择后传入 processDefinitionKey

4.3 生成采购订单

请求参数:

参数 类型 必填 说明
id Long 采购申请编号
supplierId Long 供应商编号

响应: { "code": 0, "data": 2001, "msg": "操作成功" }(返回采购订单编号)

4.4 分页查询响应

{
  "code": 0,
  "data": {
    "list": [
      {
        "id": 1,
        "no": "CGSQ20260701000001",
        "status": 20,
        "requestUserId": 1,
        "requestUserName": "张三",
        "requestDeptId": 100,
        "requestDeptName": "生产部",
        "requestTime": "2026-07-01 10:00:00",
        "requestReason": "生产需要",
        "supplierId": 1,
        "supplierName": "供应商A",
        "totalCount": 100.00,
        "totalPrice": 10000.00,
        "productNames": "产品A,产品B",
        "orderId": 2001,
        "orderNo": "CGDD20260701000001",
        "createTime": "2026-07-01 10:00:00"
      }
    ],
    "total": 1
  },
  "msg": "操作成功"
}

五、状态流转

状态值 状态名 说明
0 未提交 草稿状态,可编辑、可删除
10 审批中 已提交审批,不可修改
20 审核通过 审批通过,可生成采购订单
30 审核不通过 审批被拒绝,可重新提交
40 已取消 流程被取消

状态流转图:
草稿(0) -> 提交 -> 审批中(10) -> 审批通过(20) -> 生成采购订单 | +-> 审批不通过(30) -> 重新提交 -> 审批中(10) | +-> 已取消(40)


六、前端修改点

6.1 列表页按钮

<!-- 搜索栏 -->
<el-form :model="queryParams" ref="queryFormRef" :inline="true">
  <el-form-item label="申请单号" prop="no">
    <el-input v-model="queryParams.no" placeholder="请输入申请单号" clearable />
  </el-form-item>
  <el-form-item label="申请人" prop="requestUserId">
    <el-select v-model="queryParams.requestUserId" placeholder="请选择申请人" clearable>
      <!-- 用户列表 -->
    </el-select>
  </el-form-item>
  <el-form-item label="审批状态" prop="status">
    <el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
      <el-option label="未提交" :value="0" />
      <el-option label="审批中" :value="10" />
      <el-option label="审核通过" :value="20" />
      <el-option label="审核不通过" :value="30" />
      <el-option label="已取消" :value="40" />
    </el-select>
  </el-form-item>
  <el-form-item label="申请时间" prop="requestTime">
    <el-date-picker v-model="queryParams.requestTime" type="daterange" />
  </el-form-item>
  <el-form-item>
    <el-button type="primary" @click="handleQuery">搜索</el-button>
    <el-button @click="resetQuery">重置</el-button>
  </el-form-item>
</el-form>

<!-- 操作栏 -->
<el-row :gutter="10" class="mb8">
  <el-col :span="1.5">
    <el-button type="primary" @click="handleAdd" v-hasPermi="['erp:purchase-request:create']">新增</el-button>
  </el-col>
  <el-col :span="1.5">
    <el-button type="success" @click="handleExport" v-hasPermi="['erp:purchase-request:export']">导出</el-button>
  </el-col>
</el-row>

<!-- 表格操作列 -->
<el-table-column label="操作" align="center" width="200">
  <template #default="scope">
    <el-button link type="primary" @click="handleDetail(scope.row)">详情</el-button>
    <el-button link type="primary" @click="handleUpdate(scope.row)"
               v-if="scope.row.status === 0" v-hasPermi="['erp:purchase-request:update']">编辑</el-button>
    <el-button link type="primary" @click="handleSubmit(scope.row)"
               v-if="scope.row.status === 0" v-hasPermi="['erp:purchase-request:submit']">提交</el-button>
    <el-button link type="primary" @click="handleGenerateOrder(scope.row)"
               v-if="scope.row.status === 20 && !scope.row.orderId" v-hasPermi="['erp:purchase-request:generate-order']">生成订单</el-button>
    <el-button link type="danger" @click="handleDelete(scope.row)"
               v-if="scope.row.status === 0" v-hasPermi="['erp:purchase-request:delete']">删除</el-button>
  </template>
</el-table-column>

6.2 data 数据

data() {
  return {
    // 查询参数
    queryParams: {
      pageNo: 1,
      pageSize: 10,
      no: undefined,
      requestUserId: undefined,
      requestDeptId: undefined,
      requestTime: [],
      status: undefined,
      productId: undefined,
    },
    // 状态字典
    statusOptions: [
      { value: 0, label: '未提交' },
      { value: 10, label: '审批中' },
      { value: 20, label: '审核通过' },
      { value: 30, label: '审核不通过' },
      { value: 40, label: '已取消' },
    ],
  }
}

6.3 方法

methods: {
  // 提交审批
  async handleSubmit(row) {
    try {
      await this.$modal.confirm('确认提交该采购申请进行审批?')
      await submitPurchaseRequest(row.id)
      this.$modal.msgSuccess('提交成功')
      this.getList()
    } catch {}
  },

  // 生成采购订单
  async handleGenerateOrder(row) {
    try {
      // 弹窗选择供应商
      const { value: supplierId } = await this.$prompt('请选择供应商', '生成采购订单', {
        inputType: 'select',
        inputOptions: this.supplierOptions,
        inputValidator: (value) => {
          if (!value) return '请选择供应商'
          return true
        }
      })
      const orderId = await generatePurchaseOrder(row.id, supplierId)
      this.$modal.msgSuccess(`生成采购订单成功,订单编号:${orderId}`)
      this.getList()
    } catch {}
  },
}

6.4 文件上传组件

使用通用文件上传接口 POST /infra/file/upload,详见 docs/file_upload_guide.md

<!-- 表单中的附件上传 -->
<el-form-item label="附件" prop="fileUrl">
  <el-upload
    :action="uploadUrl"
    :headers="headers"
    :data="{ directory: 'purchase-request' }"
    :on-success="handleUploadSuccess"
    :before-upload="beforeUpload"
    :file-list="fileList"
    :limit="1"
  >
    <el-button type="primary">点击上传</el-button>
    <template #tip>
      <div class="el-upload__tip">支持 pdf、doc、docx、xls、xlsx 格式,最大 10MB</div>
    </template>
  </el-upload>
</el-form-item>
data() {
  return {
    // 文件上传配置(使用通用接口)
    uploadUrl: process.env.VUE_APP_BASE_API + '/infra/file/upload',
    headers: { Authorization: 'Bearer ' + getToken() },
    fileList: [],
  }
},
methods: {
  handleUploadSuccess(response) {
    if (response.code === 0) {
      this.form.fileUrl = response.data
      this.$modal.msgSuccess('上传成功')
    } else {
      this.$modal.msgError(response.msg || '上传失败')
    }
  },
  beforeUpload(file) {
    const allowedTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                          'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']
    const isAllowed = allowedTypes.includes(file.type) || file.name.endsWith('.pdf') || file.name.endsWith('.doc') || file.name.endsWith('.docx')
                       || file.name.endsWith('.xls') || file.name.endsWith('.xlsx')
    if (!isAllowed) {
      this.$message.error('只支持 pdf、doc、docx、xls、xlsx 格式!')
      return false
    }
    const isLt10M = file.size / 1024 / 1024 < 10
    if (!isLt10M) {
      this.$message.error('文件大小不能超过 10MB!')
      return false
    }
    return true
  },
}

七、权限配置

权限标识 说明
erp:purchase-request:query 查询采购申请
erp:purchase-request:create 新增采购申请
erp:purchase-request:update 修改采购申请
erp:purchase-request:delete 删除采购申请
erp:purchase-request:submit 提交审批
erp:purchase-request:export 导出采购申请
erp:purchase-request:generate-order 生成采购订单

八、注意事项

  1. 状态限制:只有草稿状态(status=0)的申请单才能编辑和删除
  2. 审批流程:提交审批前请确保 BPM 流程已配置完成
  3. 生成订单:只有审批通过(status=20)且未生成订单的申请单才能生成采购订单
  4. 供应商选择:生成采购订单时必须选择供应商,申请时可预先指定供应商
  5. 数据完整性:申请明细需填写完整的产品信息和数量