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

物料主数据模块 (MDM) 前端变更文档

一、新增页面

1.1 物料主数据管理

涉及页面

  • 物料列表页 (views/mdm/item/index.vue)
  • 物料新增/编辑弹窗 (views/mdm/item/ItemForm.vue)
  • 物料详情页 (views/mdm/item/detail.vue)

API

方法 路径 说明
GET /mdm/item/page 物料分页查询
GET /mdm/item/list 物料列表查询
GET /mdm/item/get 获取物料详情
POST /mdm/item/create 创建物料
PUT /mdm/item/update 更新物料
DELETE /mdm/item/delete 删除物料
PUT /mdm/item/update-status 更新物料状态

请求参数(物料查询):

参数 类型 必填 说明
code String 物料编码
name String 物料名称
categoryId Long 分类ID
itemType Integer 物料类型(1:原料,2:半成品,3:成品,4:辅料)
status Integer 状态

响应:

{
  "code": 200,
  "data": {
    "list": [
      {
        "id": 1,
        "code": "M001",
        "name": "物料名称",
        "barCode": "条码",
        "specification": "规格型号",
        "categoryId": 10,
        "categoryName": "分类名称",
        "unitMeasureId": 1,
        "unitMeasureName": "单位名称",
        "brandId": 1,
        "brandName": "品牌名称",
        "itemType": 1,
        "status": 0,
        "purchasePrice": 100.00,
        "salesPrice": 150.00,
        "costPrice": 80.00,
        "safetyStock": 50.00,
        "minStock": 20.00,
        "maxStock": 200.00,
        "isBatchManaged": true,
        "expiryDay": 365,
        "remark": "备注"
      }
    ],
    "total": 100
  }
}

前端修改点

1. 物料列表页面结构:

<template>
  <ContentWrap>
    <!-- 搜索区域 -->
    <el-form :model="queryParams" ref="queryFormRef" :inline="true">
      <el-form-item label="物料编码" prop="code">
        <el-input v-model="queryParams.code" placeholder="请输入物料编码" />
      </el-form-item>
      <el-form-item label="物料名称" prop="name">
        <el-input v-model="queryParams.name" placeholder="请输入物料名称" />
      </el-form-item>
      <el-form-item label="物料分类" prop="categoryId">
        <el-tree-select v-model="queryParams.categoryId" :data="categoryTree" />
      </el-form-item>
      <el-form-item label="物料类型" prop="itemType">
        <el-select v-model="queryParams.itemType" placeholder="请选择物料类型">
          <el-option label="原料" :value="1" />
          <el-option label="半成品" :value="2" />
          <el-option label="成品" :value="3" />
          <el-option label="辅料" :value="4" />
        </el-select>
      </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" plain @click="handleCreate">新增</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="success" plain @click="handleExport">导出</el-button>
      </el-col>
    </el-row>

    <!-- 表格 -->
    <el-table v-loading="loading" :data="list">
      <el-table-column label="物料编码" prop="code" width="120" />
      <el-table-column label="物料名称" prop="name" width="180" />
      <el-table-column label="规格型号" prop="specification" width="150" />
      <el-table-column label="分类" prop="categoryName" width="100" />
      <el-table-column label="单位" prop="unitMeasureName" width="80" />
      <el-table-column label="物料类型" prop="itemType" width="80">
        <template #default="{ row }">
          <dict-tag :type="DICT_TYPE.MDM_ITEM_TYPE" :value="row.itemType" />
        </template>
      </el-table-column>
      <el-table-column label="采购价" prop="purchasePrice" width="100" />
      <el-table-column label="销售价" prop="salesPrice" width="100" />
      <el-table-column label="批次管理" prop="isBatchManaged" width="80">
        <template #default="{ row }">
          <el-tag v-if="row.isBatchManaged" type="success">是</el-tag>
          <el-tag v-else type="info">否</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="状态" prop="status" width="80">
        <template #default="{ row }">
          <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" />
        </template>
      </el-table-column>
      <el-table-column label="操作" width="180" fixed="right">
        <template #default="{ row }">
          <el-button link type="primary" @click="handleUpdate(row)">编辑</el-button>
          <el-button link type="danger" @click="handleDelete(row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <!-- 分页 -->
    <Pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
  </ContentWrap>
</template>

2. 物料表单弹窗:

<el-dialog v-model="dialogVisible" title="物料信息" width="800px">
  <el-form ref="formRef" :model="formData" :rules="formRules" label-width="120px">
    <el-row :gutter="20">
      <el-col :span="12">
        <el-form-item label="物料编码" prop="code">
          <el-input v-model="formData.code" placeholder="请输入物料编码" />
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="物料名称" prop="name">
          <el-input v-model="formData.name" placeholder="请输入物料名称" />
        </el-form-item>
      </el-col>
    </el-row>
    <el-row :gutter="20">
      <el-col :span="12">
        <el-form-item label="条码" prop="barCode">
          <el-input v-model="formData.barCode" placeholder="请输入条码" />
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="规格型号" prop="specification">
          <el-input v-model="formData.specification" placeholder="请输入规格型号" />
        </el-form-item>
      </el-col>
    </el-row>
    <el-row :gutter="20">
      <el-col :span="12">
        <el-form-item label="物料分类" prop="categoryId">
          <el-tree-select v-model="formData.categoryId" :data="categoryTree" />
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="计量单位" prop="unitMeasureId">
          <el-select v-model="formData.unitMeasureId" placeholder="请选择单位">
            <el-option v-for="unit in unitList" :key="unit.id" :label="unit.name" :value="unit.id" />
          </el-select>
        </el-form-item>
      </el-col>
    </el-row>
    <el-row :gutter="20">
      <el-col :span="12">
        <el-form-item label="品牌" prop="brandId">
          <el-select v-model="formData.brandId" placeholder="请选择品牌">
            <el-option v-for="brand in brandList" :key="brand.id" :label="brand.name" :value="brand.id" />
          </el-select>
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="物料类型" prop="itemType">
          <el-select v-model="formData.itemType" placeholder="请选择物料类型">
            <el-option label="原料" :value="1" />
            <el-option label="半成品" :value="2" />
            <el-option label="成品" :value="3" />
            <el-option label="辅料" :value="4" />
          </el-select>
        </el-form-item>
      </el-col>
    </el-row>
    <!-- 价格信息 -->
    <el-row :gutter="20">
      <el-col :span="8">
        <el-form-item label="采购价" prop="purchasePrice">
          <el-input-number v-model="formData.purchasePrice" :precision="2" />
        </el-form-item>
      </el-col>
      <el-col :span="8">
        <el-form-item label="销售价" prop="salesPrice">
          <el-input-number v-model="formData.salesPrice" :precision="2" />
        </el-form-item>
      </el-col>
      <el-col :span="8">
        <el-form-item label="成本价" prop="costPrice">
          <el-input-number v-model="formData.costPrice" :precision="2" />
        </el-form-item>
      </el-col>
    </el-row>
    <!-- 库存管理 -->
    <el-row :gutter="20">
      <el-col :span="12">
        <el-form-item label="安全库存" prop="safetyStock">
          <el-input-number v-model="formData.safetyStock" :precision="2" />
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="批次管理" prop="isBatchManaged">
          <el-switch v-model="formData.isBatchManaged" />
        </el-form-item>
      </el-col>
    </el-row>
    <el-form-item label="备注" prop="remark">
      <el-input v-model="formData.remark" type="textarea" :rows="3" />
    </el-form-item>
  </el-form>
  <template #footer>
    <el-button @click="dialogVisible = false">取消</el-button>
    <el-button type="primary" @click="submitForm">确定</el-button>
  </template>
</el-dialog>

3. 数据定义:

<script setup>
import { ref, reactive, onMounted } from 'vue'
import * as ItemApi from '@/api/mdm/item'

const loading = ref(false)
const list = ref([])
const total = ref(0)
const queryParams = reactive({
  pageNo: 1,
  pageSize: 10,
  code: '',
  name: '',
  categoryId: null,
  itemType: null,
  status: null
})

const dialogVisible = ref(false)
const formData = ref({
  id: undefined,
  code: '',
  name: '',
  barCode: '',
  specification: '',
  categoryId: null,
  unitMeasureId: null,
  brandId: null,
  itemType: 1,
  purchasePrice: null,
  salesPrice: null,
  costPrice: null,
  safetyStock: null,
  isBatchManaged: false,
  remark: ''
})

const getList = async () => {
  loading.value = true
  try {
    const data = await ItemApi.getItemPage(queryParams)
    list.value = data.list
    total.value = data.total
  } finally {
    loading.value = false
  }
}

const handleCreate = () => {
  formData.value = { ...initialFormData }
  dialogVisible.value = true
}

const handleUpdate = (row) => {
  formData.value = { ...row }
  dialogVisible.value = true
}

const submitForm = async () => {
  await formRef.value.validate()
  if (formData.value.id) {
    await ItemApi.updateItem(formData.value)
  } else {
    await ItemApi.createItem(formData.value)
  }
  dialogVisible.value = false
  getList()
}

onMounted(() => {
  getList()
})
</script>

1.2 物料分类管理

涉及页面

  • 物料分类管理页 (views/mdm/category/index.vue)

API

方法 路径 说明
GET /mdm/category/list 分类列表查询
GET /mdm/category/get 获取分类详情
POST /mdm/category/create 创建分类
PUT /mdm/category/update 更新分类
DELETE /mdm/category/delete 删除分类

1.3 计量单位管理

涉及页面

  • 计量单位管理页 (views/mdm/unit/index.vue)

API

方法 路径 说明
GET /mdm/unit/page 单位分页查询
GET /mdm/unit/list 单位列表查询
POST /mdm/unit/create 创建单位
PUT /mdm/unit/update 更新单位
DELETE /mdm/unit/delete 删除单位

1.4 品牌管理

涉及页面

  • 品牌管理页 (views/mdm/brand/index.vue)

API

方法 路径 说明
GET /mdm/brand/page 品牌分页查询
GET /mdm/brand/list 品牌列表查询
POST /mdm/brand/create 创建品牌
PUT /mdm/brand/update 更新品牌
DELETE /mdm/brand/delete 删除品牌

二、修改页面

2.1 ERP 产品管理页面

修改内容

原页面views/erp/product/index.vue

修改点
1. API 接口从 /erp/product/* 改为调用 /mdm/item/*
2. 数据字段映射调整(productIditemId
3. 增加物料类型筛选(原料/半成品/成品/辅料)

注意事项
- ERP 产品页面数据来源从 MDM 物料获取
- 保留 ERP 特有字段(采购价、销售价、最低价)的编辑能力


2.2 MES 物料管理页面

修改内容

原页面views/mes/md/item/index.vue

修改点
1. API 接口从 /mes/md-item/* 改为调用 /mdm/item/*
2. 数据字段映射调整(itemTypeIdcategoryId
3. 批次配置从独立页面改为物料详情页子模块

注意事项
- MES 物料页面数据来源从 MDM 物料获取
- 批次属性配置保留在 MDM 模块管理


2.3 WMS 商品管理页面

修改内容

原页面views/wms/item/index.vue

修改点
1. API 接口从 /wms/item/* 改为调用 /mdm/item/*
2. SKU 管理改为物料详情页子模块
3. 库存查询改用统一接口 /wms/stock/*

注意事项
- WMS 商品页面数据来源从 MDM 物料获取
- SKU 作为物料的规格属性管理


三、新增字典类型

字典类型 字典值 说明
MDM_ITEM_TYPE 1 原料
MDM_ITEM_TYPE 2 半成品
MDM_ITEM_TYPE 3 成品
MDM_ITEM_TYPE 4 辅料
STOCK_BIZ_TYPE 10 采购入库
STOCK_BIZ_TYPE 20 销售出库
STOCK_BIZ_TYPE 30 生产入库
STOCK_BIZ_TYPE 40 生产领料
STOCK_BIZ_TYPE 50 生产退料
STOCK_BIZ_TYPE 60 采购退货出库
STOCK_BIZ_TYPE 70 销售退货入库
STOCK_BIZ_TYPE 80 调拨入库
STOCK_BIZ_TYPE 90 调拨出库
STOCK_BIZ_TYPE 100 盘盈入库
STOCK_BIZ_TYPE 110 盘亏出库

四、路由配置

// 新增路由
{
  path: '/mdm',
  component: Layout,
  name: 'MDM',
  meta: { title: '主数据管理', icon: 'ep:goods' },
  children: [
    {
      path: 'item',
      name: 'MdmItem',
      component: () => import('@/views/mdm/item/index.vue'),
      meta: { title: '物料管理' }
    },
    {
      path: 'category',
      name: 'MdmCategory',
      component: () => import('@/views/mdm/category/index.vue'),
      meta: { title: '物料分类' }
    },
    {
      path: 'unit',
      name: 'MdmUnit',
      component: () => import('@/views/mdm/unit/index.vue'),
      meta: { title: '计量单位' }
    },
    {
      path: 'brand',
      name: 'MdmBrand',
      component: () => import('@/views/mdm/brand/index.vue'),
      meta: { title: '品牌管理' }
    },
    {
      path: 'warehouse',
      name: 'MdmWarehouse',
      component: () => import('@/views/mdm/warehouse/index.vue'),
      meta: { title: '仓库管理' }
    }
  ]
}

五、注意事项

  1. 数据迁移:执行数据迁移 SQL 后,原有 ERP/MES/WMS 的物料页面将展示迁移后的 MDM 数据
  2. 权限配置:新增 MDM 模块菜单和权限配置
  3. API 对接:前端需要新增 MDM 相关 API 文件 (api/mdm/item.js, api/mdm/category.js 等)
  4. 字段兼容:旧页面的字段名称需要映射到新字段,如 productIditemId
  5. 状态同步:物料状态变更后,需要同步更新各模块引用状态

文档版本: v1.0
创建日期: 2026-06-29
作者: Claude Code