feat(物料管理): 添加MRP清单功能模块

新增MRP清单管理页面及相关API接口,包括:
1. 添加mmMrpManagement.js API文件,提供MRP清单查询和生成接口
2. 创建MrpList.vue和WorkOrder.vue视图组件
3. 配置vue.config.js代理规则对接总成MES系统
4. 移除废弃的production_track.vue文件
This commit is contained in:
2025-08-13 18:08:08 +08:00
parent 09de578c24
commit 262a5b19e2
6 changed files with 508 additions and 4 deletions

View File

@@ -0,0 +1,75 @@
import request from '@/utils/request'
// 特殊请求对接总成MES数据
let baseUrl = "/assembly-api/"
/**
* 生产工单分页查询
* @param {查询条件} data
*/
export function listProWorkorder(data) {
return request({
url: baseUrl + 'mes/productManagement/ProWorkorder/list',
method: 'post',
data: data
})
}
/**
* 生产工单(不校验)分页查询
* @param {查询条件} data
*/
export function listProWorkorderNoCheck(data) {
return request({
url: baseUrl + 'mes/productManagement/ProWorkorder/list_nocheck',
method: 'post',
data: data
})
}
/**
* 获取全部工艺路线
* @param {查询条件} params
*/
export function GetAllRoute() {
return request({
url: baseUrl + 'mes/productManagement/ProWorkorder/get_all_route',
method: 'get'
})
}
/**
* 获取全部组
* @param {查询条件} params
*/
export function GetAllGroup() {
return request({
url: baseUrl + 'mes/productManagement/ProWorkorder/get_groups',
method: 'get'
})
}
/**
* 根据线别生成油漆件MRP
* @param {查询条件} data
*/
export function GenerateLineMmMrp(query) {
return request({
url: baseUrl + 'mes/materialManagement/paintedparts_call/mmcall/GenerateLineMmCallMRP',
method: 'post',
data: query
})
}
/**
* MRP清单分页查询
* @param {查询条件} data
*/
export function listMmMrp(query) {
return request({
url: baseUrl + 'mes/materialManagement/paintedparts_call/mmcall/list',
method: 'get',
params: query
})
}

View File

@@ -23,6 +23,7 @@ import './permission' // permission control 动态路由
import { getDicts } from '@/api/system/dict/data'
import { getConfigKey } from '@/api/system/config'
import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, download, handleTree, handleDict } from '@/utils/ruoyi'
//分页组件
import Pagination from '@/components/Pagination'
//自定义表格工具扩展

View File

@@ -0,0 +1,203 @@
<!--
* @Descripttion: (MRP清单)
* @Author: (admin)
* @Date: (2025-08-13)
-->
<template>
<div>
<el-form :model="queryParams" label-position="right" inline ref="queryRef" v-show="showSearch" @submit.prevent>
<el-form-item label="线别" prop="lineCode">
<el-select v-model="queryParams.lineCode" placeholder="请选择线别">
<el-option label="全部" value=""></el-option>
<el-option v-for="line in lineOptions" :key="line.value" :label="line.label" :value="line.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="日期" prop="workOrderDate">
<el-date-picker v-model="queryParams.workOrderDate" :clearable="false" type="date"
placeholder="选择日期"></el-date-picker>
</el-form-item>
<el-form-item>
<el-button icon="search" type="primary" @click="handleQuery">搜索</el-button>
<el-button icon="refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 工具区域 -->
<el-row :gutter="15" class="mb10">
<el-col :span="1.5">
<el-button type="primary" plain @click="openGenerateMrpDialog">手动更新MRP清单
</el-button>
</el-col>
<right-toolbar :show-search.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row>
<el-table :data="dataList" v-loading="loading" ref="table" border header-cell-class-name="el-table-header-cell"
highlight-current-row @sort-change="sortChange">
<el-table-column type="index" width="50" align="center" />
<el-table-column prop="lineCode" label="线别" align="center" />
<el-table-column prop="materialCode" label="物料编号" align="center" />
<el-table-column prop="materialName" label="物料名称" align="center" />
<el-table-column prop="quantity" label="数量" align="center" />
<el-table-column prop="createdBy" label="创建人" align="center" />
<el-table-column prop="createdTime" label="创建时间" />
</el-table>
<pagination :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
@pagination="getList" />
<!-- 生成MRP清单对话框 -->
<el-dialog :title="'手动更新MRP清单'" :lock-scroll="false" :visible.sync="generateMrpOpen">
<el-form ref="mrpFormRef" :model="mrpForm" :rules="mrpRules" label-width="100px">
<el-row :gutter="20">
<el-col :lg="24">
<el-form-item label="线别" prop="lineCode">
<el-select v-model="mrpForm.lineCode" placeholder="请选择线别" style="width: 100%">
<el-option v-for="line in lineOptions" :key="line.value" :label="line.label"
:value="line.value"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :lg="24">
<el-form-item label="日期" prop="workOrderDate">
<el-date-picker v-model="mrpForm.workOrderDate" :clearable="false" type="date" placeholder="选择日期"
style="width: 100%"></el-date-picker>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="cancelGenerateMrp">取消</el-button>
<el-button type="primary" @click="submitGenerateMrp">提交</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
listMmMrp, GenerateLineMmMrp
}
from '@/api/materialManagement/mmMrpManagement.js'
export default {
name: 'mmMrpManagement',
data() {
// 线别选项 (1-28)
const lineOptions = []
for (let i = 1; i <= 28; i++) {
lineOptions.push({
value: i.toString(),
label: `线别${i}`
})
}
return {
ids: [],
loading: false,
showSearch: true,
queryParams: {
pageNum: 1,
pageSize: 10,
lineCode: '',
workOrderDate: '',
sort: '',
sortType: 'asc',
},
lineOptions: lineOptions,
columns: [],
total: 0,
dataList: [],
queryRef: null,
// 生成MRP相关
generateMrpOpen: false,
mrpFormRef: null,
mrpForm: {
lineCode: '1',
workOrderDate: this.$dayjs().format('YYYY-MM-DD') // 默认今天
},
mrpRules: {
lineCode: [{ required: true, message: '请选择线别', trigger: 'change' }],
workOrderDate: [{ required: true, message: '请选择日期', trigger: 'change' }]
}
}
},
created() {
this.queryParams.workOrderDate = this.$dayjs().format('YYYY-MM-DD')
this.getList()
},
methods: {
getList() {
this.loading = true
let params = { ...this.queryParams }
params.workOrderDate = this.$dayjs(params.workOrderDate).format('YYYY-MM-DD')
listMmMrp(params).then(res => {
const { code, data } = res
if (code == 200) {
this.dataList = data.result
this.total = data.totalNum
this.loading = false
}
})
},
// 查询
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
// 重置查询操作
resetQuery() {
this.resetForm("queryRef")
// 重置为默认线别和今天日期
this.queryParams.lineCode = '1'
this.queryParams.workOrderDate = this.$dayjs().format('YYYY-MM-DD')
this.handleQuery()
},
// 自定义排序
sortChange(column) {
var sort = undefined
var sortType = undefined
if (column.prop != null && column.order != null) {
sort = column.prop
sortType = column.order
}
this.queryParams.sort = sort
this.queryParams.sortType = sortType
this.handleQuery()
},
// 打开生成MRP对话框
openGenerateMrpDialog() {
this.generateMrpOpen = true
// 重置表单
this.mrpForm.lineCode = '1'
this.mrpForm.workOrderDate = this.$dayjs().format('YYYY-MM-DD')
this.resetForm("mrpFormRef")
},
// 关闭生成MRP对话框
cancelGenerateMrp() {
this.generateMrpOpen = false
},
// 提交生成MRP
submitGenerateMrp() {
this.$refs["mrpFormRef"].validate((valid) => {
if (valid) {
this.loading = true
let params = { ...this.mrpForm }
params.workOrderDate = this.$dayjs(params.workOrderDate).format('YYYY-MM-DD')
GenerateLineMmMrp(params).then(res => {
this.loading = false
if (res.code == 200) {
this.$modal.msgSuccess('生成MRP清单成功')
this.generateMrpOpen = false
this.getList()
} else {
this.$modal.msgError(res.msg || '生成失败')
}
}).catch(() => {
this.loading = false
this.$modal.msgError('生成失败')
})
}
})
}
}
}
</script>

View File

@@ -0,0 +1,208 @@
<!--
* @Descripttion: (总成生产工单)
* @Author: (admin)
* @Date: (2025-08-13)
-->
<template>
<div>
<el-form :model="queryParams" label-position="right" inline ref="queryRef" v-show="showSearch" @submit.prevent>
<div>
<el-form-item label="工单日期" prop="workorderDate">
<el-date-picker v-model="queryParams.workorderDate" type="daterange" range-separator="到"
start-placeholder="开始时间" end-placeholder="结束时间" :clearable="false" placeholder="请选择工单日期区间" />
</el-form-item>
<!-- <el-form-item label="组别" prop="groupCode">
<el-select v-model="queryParams.groupCode" placeholder="全部">
<el-option label="全部" value="" />
<el-option v-for="(item, index) in allGroupOptions" :key="index" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item> -->
<el-form-item label="线别" prop="lineCode">
<el-select v-model="queryParams.lineCode" placeholder="全部">
<el-option label="全部" value="" />
<el-option v-for="(item, index) in allRouteOptions" :key="index" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
</div>
<el-form-item label="工单号" prop="workorder">
<el-input v-model.trim="queryParams.workorder" clearable placeholder="请输入工单号" />
</el-form-item>
<el-form-item label="产品名称" prop="productionName">
<el-input v-model.trim="queryParams.productionName" clearable placeholder="请输入产品名称" />
</el-form-item>
<el-form-item>
<el-button icon="search" type="primary" @click="handleQuery">搜索</el-button>
<el-button icon="refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 工具区域 -->
<el-row :gutter="15" class="mb10">
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row>
<el-table :data="dataList" v-loading="loading" ref="table" border stripe size="small"
header-row-class-name="table-header" @sort-change="sortChange">
<el-table-column type="index" width="50" align="center" />
<el-table-column prop="workorder" label="工单号" width="160" align="center">
</el-table-column>
<el-table-column prop="productionName" label="产品名称" min-width="200" align="center" />
<el-table-column prop="productionCode" label="物料编号" width="160" align="center"></el-table-column>
<el-table-column prop="specification" label="规格" width="160" align="center" />
<el-table-column prop="deliveryNum" label="计划数量" align="center" />
<el-table-column prop="unit" label="单位" align="center" />
<el-table-column prop="lineCode" label="线别" align="center" />
<el-table-column prop="groupCode" label="组别" align="center" />
<el-table-column prop="isCarton" label="是否纸箱" align="center">
</el-table-column>
<el-table-column prop="packageCapacity" label="装箱数量" align="center" />
<el-table-column prop="workorderDate" label="工单日期" align="center" min-width="140">
<template #default="scope">
<span v-if="scope.row.workorderDate != '' && scope.row.workorderDate != null">{{
$dayjs(scope.row.workorderDate).format('YYYY-MM-DD') }}</span>
</template>
</el-table-column>
<el-table-column prop="status" label="工单状态" align="center">
</el-table-column>
<el-table-column prop="beat" label="节拍" align="center" />
<el-table-column prop="remark" label="备注" align="center" />
<el-table-column prop="createdBy" label="创建人" align="center" />
<el-table-column prop="createdTime" label="创建时间" />
<el-table-column prop="updatedBy" label="更新人" align="center" />
<el-table-column prop="updatedTime" label="更新时间" />
</el-table>
<pagination :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</div>
</template>
<script>
import {
listProWorkorderNoCheck,
GetAllRoute,
GetAllGroup
} from '@/api/materialManagement/mmMrpManagement.js'
export default {
name: 'WorkOrder',
data() {
return {
ids: [],
loading: false,
showSearch: true,
queryParams: {
pageNum: 1,
pageSize: 50,
lineCode: '',
groupCode: '',
workorderDate: [this.$dayjs(), this.$dayjs()],
status: -1,
sort: 'sort',
sortType: 'asc'
},
columns: [],
total: 0,
dataList: [],
defaultTime: [this.$dayjs(), this.$dayjs()],
dictParams: {
isCarton: [],
statusOptions: []
},
allList: [],
allRouteOptions: [],
allGroupOptions: [],
}
},
created() {
this.getAllRouteOptions()
this.getAllGroupSelectOptions()
this.getList()
},
methods: {
// =========== 获取所有线别 ==========
getAllRouteOptions() {
GetAllRoute().then((res) => {
if (res.code === 200) {
this.allRouteOptions = res.data.map((item) => {
return {
id: item.id,
label: `${item.code}-${item.name}`,
value: `${item.code}`
}
})
}
})
},
// ==================================
// =========== 获取所有组别 ==========
getAllGroupSelectOptions() {
GetAllGroup().then((res) => {
if (res.code === 200) {
this.allGroupOptions = res.data.map((item) => {
return {
id: item.id,
label: `${item.groupCode}-${item.groupName}`,
value: `${item.groupCode}`
}
})
}
})
},
// ==================================
// 不校验搜索
getList() {
this.loading = true
listProWorkorderNoCheck(this.queryParams).then((res) => {
const { code, data } = res
if (code == 200) {
this.dataList = data.result
this.total = data.totalNum
this.loading = false
}
})
let allData = JSON.parse(JSON.stringify(this.queryParams))
allData.pageNum = 1
allData.pageSize = 10000
listProWorkorderNoCheck(allData).then((res) => {
const { code, data } = res
if (code == 200) {
this.allList = data.result
}
})
},
// 查询
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
// 重置查询操作
resetQuery() {
this.$refs.queryRef.resetFields()
this.handleQuery()
},
// 自定义排序
sortChange(column) {
var sort = undefined
var sortType = undefined
if (column.prop != null && column.order != null) {
sort = column.prop
sortType = column.order
}
this.queryParams.sort = sort
this.queryParams.sortType = sortType
this.handleQuery()
},
}
}
</script>
<style scoped>
</style>

View File

@@ -37,11 +37,28 @@ module.exports = {
port: 8887, // 项目启动port,
open: true,
proxy: {
'/dev-api/assembly-api': {
target: 'http://localhost:7000', // 后端接口地址
changeOrigin: true,
logLevel: 'debug',
onProxyReq: (proxyReq, req) => {
// http请求
console.log('[HPM] %s %s %s %s', req.method, req.originalUrl, '->', req.url);
},
pathRewrite: {
'^/dev-api/assembly-api': '', //需要rewrite的
},
},
// detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_BASE_API]: {
target: 'http://localhost:8888', // 后端接口地址
// target: 'http://192.168.0.31:8888/', // 后端接口地址
changeOrigin: true,
logLevel: 'debug',
onProxyReq: (proxyReq, req) => {
// http请求
console.log('[HPM] %s %s %s %s', req.method, req.originalUrl, '->', req.url);
},
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: '', //需要rewrite的
},