feat(system): 添加物料管理和生产计划功能

- 新增物料管理页面,支持物料导入、导出和推送金蝶
- 优化生产计划页面,增加工作中心筛选功能
- 调整路由配置,增加主页和系统管理路由- 修复详情页面子项分母输入错误
This commit is contained in:
tzy 2025-02-21 10:32:31 +08:00
parent 49c99c8e4d
commit b5585458ec
13 changed files with 1393 additions and 350 deletions

View File

@ -42,3 +42,10 @@ export function delMaterials(id) {
method: 'delete'
})
}
// 推送金蝶
export function addToK3() {
return request({
url: '/system/materials/addToK3',
method: 'post'
})
}

View File

@ -172,3 +172,19 @@ export function listMaterial(query) {
params: query
})
}
// 获取工艺路线列表
export function getProcessRouteList(materialCode, materialName, productionOrderNo) {
return request({
url: '/system/route/getProcessRouteList',
method: 'get',
params: {
materialCode,
materialName,
productionOrderNo
}
})
}

View File

@ -42,9 +42,20 @@ export function delStockData(id) {
method: 'delete'
})
}
export function generateDoc() {
return request({
url: '/system/stockData/generateDoc', // 这个路径应该和你的后端接口路径一致
method: 'post'
url: '/system/stockData/generateDoc',
method: 'post',
timeout: 10 * 1000 * 60
});
}
export function logs(lastIndex) {
return request({
url: `/system/stockData/logs?lastIndex=${lastIndex}`,
method: 'get'
});
}

View File

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询金蝶工段数据列表
export function listWorkCenterData(query) {
return request({
url: '/system/workCenterData/list',
method: 'get',
params: query
})
}
// 查询金蝶工段数据详细
export function getWorkCenterData(id) {
return request({
url: '/system/workCenterData/' + id,
method: 'get'
})
}
// 新增金蝶工段数据
export function addWorkCenterData(data) {
return request({
url: '/system/workCenterData',
method: 'post',
data: data
})
}
// 修改金蝶工段数据
export function updateWorkCenterData(data) {
return request({
url: '/system/workCenterData',
method: 'put',
data: data
})
}
// 删除金蝶工段数据
export function delWorkCenterData(id) {
return request({
url: '/system/workCenterData/' + id,
method: 'delete'
})
}

View File

@ -30,6 +30,24 @@ import Layout from '@/layout'
// 公共路由
export const constantRoutes = [
{
path: '/',
component: Layout,
hidden: false,
redirect: '/home'
},
{
path: '/home',
component: Layout,
hidden: true,
redirect: '/system/productionPlan',
children: [
{
path: '/system/productionPlan',
component: () => import('@/views/system/productionPlan')
}
]
},
{
path: '/redirect',
component: Layout,

View File

@ -145,7 +145,7 @@
</el-row>
<el-table v-loading="loading" row-key="id" :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
:data="detailsList" border @selection-change="handleSelectionChange">
:data="detailsList" border :header-cell-style ="{'text-align':'center'}" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center"/>
<!-- // <el-table-column label="id" align="center" prop="id" v-if="true"/>-->
<el-table-column label="生产令号" align="center" prop="totalWeight"/>
@ -163,7 +163,7 @@
</div>
</template>
</el-table-column>
<el-table-column label="子项图号" align="center" prop="partNumber"/>
<el-table-column label="子项图号" align="left" prop="partNumber"/>
<el-table-column label="子项名称" align="center" prop="name"/>
<el-table-column label="子项分子" align="center" prop="quantity"/>
<el-table-column label="子项分母" align="center" prop="denominator"/>
@ -238,8 +238,8 @@
<el-form-item label="子项分子" prop="quantity">
<el-input v-model="form.quantity" placeholder="请输入数量"/>
</el-form-item>
<el-form-item label="子项分母" prop="quantity">
<el-input v-model="form.quantity" placeholder="请输入数量"/>
<el-form-item label="子项分母" prop="denominator">
<el-input v-model="form.denominator" placeholder="请输入数量"/>
</el-form-item>
<el-form-item label="材料" prop="material">
<el-input v-model="form.material" placeholder="请输入材料"/>
@ -301,10 +301,14 @@ import {listDetails, getDetails, delDetails, addDetails, updateDetails, updateFB
import upload from "svg-sprite-loader/examples/custom-runtime-generator/build/main";
import {getToken} from "@/utils/auth";
import axios from "axios";
import {align} from "quill/ui/icons";
export default {
name: "Details",
computed: {
align() {
return align
},
upload() {
return upload
}
@ -343,6 +347,7 @@ export default {
name: undefined,
stats: undefined,
quantity: undefined,
denominator:undefined,
material: undefined,
unitWeight: undefined,
totalWeight: undefined,

View File

@ -2,60 +2,43 @@
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="序号" prop="serialNumber">
<el-input
v-model="queryParams.serialNumber"
placeholder="请输入序号"
clearable
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.serialNumber" placeholder="请输入序号" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="物料编码" prop="materialCode">
<el-input
v-model="queryParams.materialCode"
placeholder="请输入物料编码"
clearable
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.materialCode" placeholder="请输入物料编码" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="物料名称" prop="materialName">
<el-input
v-model="queryParams.materialName"
placeholder="请输入物料名称"
clearable
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.materialName" placeholder="请输入物料名称" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="型号" prop="model">
<el-input
v-model="queryParams.model"
placeholder="请输入型号"
clearable
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.model" placeholder="请输入型号" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="单位" prop="unit">
<el-input
v-model="queryParams.unit"
placeholder="请输入单位"
clearable
@keyup.enter.native="handleQuery"
/>
<el-form-item label="类别" prop="materialType">
<el-select v-model="queryParams.materialType" placeholder="类别" clearable @keyup.enter.native="handleQuery">
<el-option label="传感器元件-DC" value="DC"></el-option>
<el-option label="配电元件-DP" value="DP"></el-option>
<el-option label="控制器元件-DK" value="DK"></el-option>
<el-option label="通讯元件-DT" value="DT"></el-option>
<el-option label="驱动器-DQ" value="DQ"></el-option>
<el-option label="电机-DD" value="DD"></el-option>
<el-option label="辅料元件-DF" value="DF"></el-option>
<el-option label="线缆-DX" value="DX"></el-option>
<el-option label="连接器元件-DL" value="DL"></el-option>
<el-option label="耗材元件-DH" value="DH"></el-option>
<el-option label="机械相关-DJ" value="DJ"></el-option>
<el-option label="电子元件-DZ" value="DZ"></el-option>
<el-option label="部件-DB" value="DB"></el-option>
</el-select>
</el-form-item>
<el-form-item label="品牌" prop="brand">
<el-input
v-model="queryParams.brand"
placeholder="请输入品牌"
clearable
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.brand" placeholder="请输入品牌" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="备注" prop="remarks">
<el-input
v-model="queryParams.remarks"
placeholder="请输入备注"
clearable
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.remarks" placeholder="请输入备注" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@ -65,112 +48,132 @@
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['system:materials:add']"
>新增</el-button>
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
v-hasPermi="['system:materials:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['system:materials:edit']"
>修改</el-button>
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
v-hasPermi="['system:materials:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['system:materials:remove']"
>删除</el-button>
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
v-hasPermi="['system:materials:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['system:materials:export']"
>导出</el-button>
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
v-hasPermi="['system:materials:export']">导出</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="el-icon-check" size="mini" @click="pushToK3"
v-permission="['system:materials:addToK3']">推送金蝶</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-upload" size="mini" @click="handleImportTime"
v-permission="['system:materials:importData']">导入
</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-if="showExportButton" type="primary" size="mini" @click="exportImportedData"
v-permission="['system:materials:exportData']"
>导出数据</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="materialsList" @selection-change="handleSelectionChange">
<el-table v-loading="loading" :data="materialsList" border @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" prop="serialNumber" />
<el-table-column label="物料编码" align="center" prop="materialCode" />
<el-table-column label="物料名称" align="center" prop="materialName" />
<el-table-column label="型号" align="center" prop="model" />
<el-table-column label="材质" align="center" prop="materialType" />
<el-table-column label="物料编码" align="left" prop="materialCode" />
<el-table-column label="物料名称" align="left" prop="materialName" />
<el-table-column label="型号" align="left" prop="model" />
<el-table-column label="类别" align="center" prop="materialType" />
<el-table-column label="单位" align="center" prop="unit" />
<el-table-column label="品牌" align="center" prop="brand" />
<el-table-column label="物料状态" align="center" prop="materialValue">
<template slot-scope="scope">
<dict-tag :options="dict.type.material_status" :value="scope.row.materialValue"></dict-tag>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remarks" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['system:materials:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['system:materials:remove']"
>删除</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
v-hasPermi="['system:materials:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['system:materials:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
@pagination="getList" />
<!-- 添加或修改电器物料管理对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="序号" prop="serialNumber">
<el-input v-model="form.serialNumber" placeholder="请输入序号" />
</el-form-item>
<el-form-item label="物料编码" prop="materialCode">
<el-input v-model="form.materialCode" placeholder="请输入物料编码" />
</el-form-item>
<el-form-item label="物料名称" prop="materialName">
<el-input v-model="form.materialName" placeholder="请输入物料名称" />
</el-form-item>
<!-- 型号搜索框 -->
<el-form-item label="型号" prop="model">
<el-input v-model="form.model" placeholder="请输入型号" />
</el-form-item>
<el-form-item label="单位" prop="unit">
<el-input v-model="form.unit" placeholder="请输入单位" />
<el-autocomplete v-model="form.model" :fetch-suggestions="handleModelSearch" :trigger-on-focus="false"
@select="handleModelSelect" placeholder="请输入型号" clearable style="width: 100%">
<template slot-scope="{ item }">
<div class="material-suggestion-item">
<div class="material-info">
<span>{{ item.model }}</span>
<el-tag size="mini" :type="item.materialValue === '1' ? 'success' : 'danger'"
style="margin-left: 8px">
{{ item.materialValue === '1' ? '有' : '无' }}
</el-tag>
</div>
<div class="sub-info">
{{ item.materialCode }} | {{ item.materialName }} | {{ item.brand }}
</div>
</div>
</template>
</el-autocomplete>
</el-form-item>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="品牌" prop="brand">
<el-input v-model="form.brand" placeholder="请输入品牌" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="名称" prop="materialName">
<el-input v-model="form.materialName" placeholder="物料名称" />
</el-form-item>
</el-col>
</el-row>
<!-- 添加类别下拉框 -->
<el-form-item label="类别" prop="materialType">
<el-select v-model="form.materialType" placeholder="请选择类别">
<el-option label="传感器元件-DC" value="DC"></el-option>
<el-option label="配电元件-DP" value="DP"></el-option>
<el-option label="控制器元件-DK" value="DK"></el-option>
<el-option label="通讯元件-DT" value="DT"></el-option>
<el-option label="驱动器-DQ" value="DQ"></el-option>
<el-option label="电机-DD" value="DD"></el-option>
<el-option label="辅料元件-DF" value="DF"></el-option>
<el-option label="线缆-DX" value="DX"></el-option>
<el-option label="连接器元件-DL" value="DL"></el-option>
<el-option label="耗材元件-DH" value="DH"></el-option>
<el-option label="机械相关-DJ" value="DJ"></el-option>
<el-option label="电子元件-DZ" value="DZ"></el-option>
<el-option label="部件-DB" value="DB"></el-option>
</el-select>
</el-form-item>
<!-- 添加单位输入框 -->
<el-form-item label="单位" prop="unit">
<el-input v-model="form.unit" placeholder="请输入单位" />
</el-form-item>
<!-- 添加备注输入框 -->
<el-form-item label="备注" prop="remarks">
<el-input v-model="form.remarks" type="textarea" placeholder="请输入内容" />
<el-input type="textarea" v-model="form.remarks" placeholder="请输入备注" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
@ -178,16 +181,66 @@
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<!-- 导入对话框 -->
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
<el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers"
:action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading"
:on-progress="handleTimeFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<span>仅允许导入xlsxlsx格式文件</span>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitTimeFileForm"> </el-button>
<el-button @click="upload.open = false"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listMaterials, getMaterials, delMaterials, addMaterials, updateMaterials } from "@/api/system/materials";
import { listMaterials, getMaterials, delMaterials, addMaterials, updateMaterials,addToK3 } from "@/api/system/materials";
import dict from "@/utils/dict";
import DictData from "@/components/DictData";
import { getToken } from "@/utils/auth";
import upload from "svg-sprite-loader/examples/custom-runtime-generator/build/main";
import { Loading, Message } from "element-ui";
import { blobValidate, tansParams } from "@/utils/ruoyi";
import errorCode from "@/utils/errorCode";
import service from "@/utils/request";
DictData.install();
export default {
name: "Materials",
computed: {
upload() {
return upload
}
},
dicts: ['material_status'],
data() {
return {
//
showExportButton: false,
//
exportDataList: [],
upload: {
//
open: false,
//
title: "",
//
isUploading: false,
//
updateSupport: 0,
//
headers: { Authorization: "Bearer " + getToken() },
//
url: process.env.VUE_APP_BASE_API + "/system/materials/importData"
},
modelSearchLoading: false,
// loading
buttonLoading: false,
//
@ -211,7 +264,7 @@ export default {
//
queryParams: {
pageNum: 1,
pageSize: 10,
pageSize: 100,
serialNumber: undefined,
materialCode: undefined,
materialName: undefined,
@ -219,18 +272,13 @@ export default {
materialType: undefined,
unit: undefined,
brand: undefined,
materialValue: undefined,
remarks: undefined
},
//
form: {},
//
rules: {
id: [
{ required: true, message: "不能为空", trigger: "blur" }
],
serialNumber: [
{ required: true, message: "序号不能为空", trigger: "blur" }
],
materialCode: [
{ required: true, message: "物料编码不能为空", trigger: "blur" }
],
@ -241,16 +289,10 @@ export default {
{ required: true, message: "型号不能为空", trigger: "blur" }
],
materialType: [
{ required: true, message: "材质不能为空", trigger: "change" }
],
unit: [
{ required: true, message: "单位不能为空", trigger: "blur" }
{ required: true, message: "类别不能为空", trigger: "blur" }
],
brand: [
{ required: true, message: "品牌不能为空", trigger: "blur" }
],
remarks: [
{ required: true, message: "备注不能为空", trigger: "blur" }
]
}
};
@ -259,6 +301,163 @@ export default {
this.getList();
},
methods: {
pushToK3() {
addToK3() //
.then(response => {
if (response.data.code === 200) {
this.$message.success('物料已成功推送至金蝶!');
} else {
this.$message.error('推送金蝶失败:' + response.data.msg);
}
})
.catch(error => {
console.error('推送金蝶失败:', error);
this.$message.error('推送金蝶失败,请重试。');
});
},
exportImportedData() {
if (this.exportDataList.length > 0) {
this.downloadJSON('system/materials/exportData', { list: this.exportDataList }, `materials_${new Date().getTime()}.xlsx`);
} else {
this.$message.warning('没有可导出的数据。');
}
},
handleImportTime() {
this.upload.title = "导入";
this.upload.open = true;
},
handleTimeFileUploadProgress(event, file, fileList) {
this.upload.isUploading = true;
},
handleFileSuccess(response, file, fileList) {
this.upload.open = false;
this.upload.isUploading = false;
this.$refs.upload.clearFiles();
//
if (response.list && response.list.length > 0) {
this.$alert("导入成功!", "导入结果", { type: 'success' });
//
this.showExportButton = true; //
this.exportDataList = response.list; //
} else {
this.$alert("导入的数据无效,请检查文件格式和内容。", "导入结果", { type: 'error' });
}
},
downloadJSON(url, params, filename, config) {
return service.post(url, params, {
headers: { 'Content-Type': 'application/json' },
responseType: 'blob',
...config
}).then(async (data) => {
const isBlob = blobValidate(data);
if (isBlob) {
const blob = new Blob([data]);
saveAs(blob, filename);
} else {
const resText = await data.text();
const rspObj = JSON.parse(resText);
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'];
Message.error(errMsg);
}
}).catch((r) => {
console.error(r);
Message.error('下载文件出现错误,请联系管理员!');
});
},
submitTimeFileForm() {
this.$nextTick(() => {
if (this.$refs.upload) {
this.$refs.upload.submit();
} else {
console.error('Upload ref is undefined');
}
});
},
//
handleModelSearch(queryString, callback) {
if (queryString.length === 0) {
callback([]);
return;
}
this.modelSearchLoading = true;
listMaterials({
pageNum: 1,
pageSize: 100,
model: queryString
}).then(response => {
const suggestions = response.rows.map(item => ({
materialCode: item.materialCode,
materialName: item.materialName,
materialType: item.materialType,
model: item.model,
brand: item.brand,
materialValue: item.materialValue //
}));
//
if (suggestions.length === 0) {
this.$message.warning('未找到对应的物料,请输入类别以生成新的物料编码。');
this.generateMaterialCode(); //
}
callback(suggestions);
}).catch(error => {
console.error('搜索物料失败:', error);
callback([]);
}).finally(() => {
this.modelSearchLoading = false;
});
},
generateMaterialCode() {
const materialType = this.form.materialType; //
if (!materialType) {
this.$message.warning('请先选择类别。');
return;
}
//
const prefix = materialType.charAt(0).toUpperCase(); //
const baseCode = `${prefix}0000000000`; //
this.form.materialCode = this.getNextMaterialCode(baseCode);
},
getNextMaterialCode(baseCode) {
//
// ["DC0000000001", "DC0000000002"]
const existingCodes = ["DC0000000001", "DC0000000002"]; //
let nextCode = baseCode;
//
for (let i = 1; i <= 9999999999; i++) {
const newCode = `${nextCode.slice(0, -10)}${(parseInt(nextCode.slice(-10)) + i).toString().padStart(10, '0')}`;
if (!existingCodes.includes(newCode)) {
return newCode;
}
}
return null; //
},
//
handleModelSelect(item) {
if (item) {
//
this.form = {
...this.form, //
materialCode: item.materialCode,
materialType: item.materialType,
materialName: item.materialName,
model: item.model,
brand: item.brand
};
}
},
dict,
/** 查询电器物料管理列表 */
getList() {
this.loading = true;
@ -284,6 +483,7 @@ export default {
materialType: undefined,
unit: undefined,
brand: undefined,
materialValue: undefined,
remarks: undefined
};
this.resetForm("form");
@ -301,14 +501,14 @@ export default {
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!==1
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加电器物料管理";
this.title = "添加电气物料";
},
/** 修改按钮操作 */
handleUpdate(row) {
@ -371,3 +571,34 @@ export default {
}
};
</script>
<style scoped>
.material-suggestion-item {
padding: 8px;
}
.material-info {
display: flex;
align-items: center;
font-size: 14px;
color: #303133;
}
.sub-info {
margin-top: 4px;
font-size: 12px;
color: #909399;
}
/* 下拉框样式 */
:deep(.el-autocomplete-suggestion__wrap) {
max-height: 280px;
}
:deep(.el-dialog) {
margin-top: 15vh !important;
}
:deep(.el-form-item) {
margin-bottom: 18px;
}
</style>

View File

@ -10,6 +10,14 @@
</el-select>
</div>
<div class="search-item">
<span>工作中心:</span>
<el-select v-model="searchParams.workCenter" placeholder="请选择工作中心" @change="search">
<el-option v-for="item in workCenterOptions" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
</div>
<div class="title">在产主要项目进度分析</div>
</div>
<div ref="gantt" class="gantt-container"></div>
@ -54,7 +62,20 @@ export default {
value: '8',
label: '外购 件'
}],
value: '1'
value: '1',
searchParams: {
workCenter: ''
},
workCenterOptions: [
{
value: '车间1',
label: '车间1'
},
{
value: '车间2',
label: '车间2'
}
]
}
},
created() {
@ -233,6 +254,30 @@ export default {
console.error('Error fetching tasks:', error);
this.loading = false;
})
},
search() {
//
const params = {
...this.searchParams,
text: this.options.find(option => option.value === this.value).label
};
// API
listProcedureGX(params).then(response => {
//
if (response && Array.isArray(response)) {
// ...
// selectChange
// ...
gantt.clearAll();
gantt.parse(this.tasks);
} else {
console.error('Invalid response data:', response);
}
}).catch(error => {
console.error('Error fetching tasks:', error);
});
}
},
@ -241,6 +286,7 @@ export default {
this.initData()
gantt.config.autofit = true;
gantt.config.autosize = true;
//, 使,
gantt.config.autosize = true
//
@ -261,19 +307,11 @@ export default {
node.setAttribute("class", "gantt_cell gantt_last_cell gantt_cell_tree " + task.status);
}
},
{name: "materialCode", label: "物料编码", width: 120, resize: true, align: "left"},
{name: "materialName", label: "物料名称", width: 150, resize: true, align: "left"},
{name: "start_date", label: "开始时间", width: 120, resize: true, align: "left"},
{name: "day", label: "天数", width: 56, resize: true, align: "left"},
{name: 'end_date', label: '完成时间', min_width: 120, resize: true, align: "left"},
// {
// name: 'duration',
// label: '',
// align: 'center',
// template: function (obj) {
// return obj.duration + ''
// },
// hide: true
// },
{name: "duration", label: "天数", width: 80, resize: true, align: "center"},
{name: 'end_date', label: '完成时间', width: 120, resize: true, align: "left"},
]
@ -542,10 +580,10 @@ export default {
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
height: 100%;
overflow: auto;
}
.container {
@ -673,4 +711,24 @@ body {
text-align: left;
padding-left: 10px;
}
.search-item {
display: flex;
align-items: center;
margin-left: 20px;
}
.search-item span {
margin-right: 10px;
}
.gantt-container {
width: 100%;
height: 100%;
}
#app {
width: 100%;
height: 100%;
}
</style>

View File

@ -32,7 +32,7 @@
<el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" />
<el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
<dict-tag :options="dict.type.material_status" :value="scope.row.status"/>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
@ -58,8 +58,11 @@
<script>
import { unallocatedUserList, authUserSelectAll } from "@/api/system/role";
import dict from "@/utils/dict";
import DictData from "@/components/DictData";
DictData.install();
export default {
dicts: ['sys_normal_disable'],
dicts: ['material_status'],
props: {
//
roleId: {
@ -87,6 +90,7 @@ export default {
};
},
methods: {
dict,
//
show() {
this.queryParams.roleId = this.roleId;

View File

@ -93,12 +93,12 @@
scope.row.routeDescription }}</router-link>
</template>
</el-table-column> -->
<el-table-column label="物料编码" width="100" align="center" prop="materialCode" />
<el-table-column label="名称" width="100" align="center" prop="materialName" />
<el-table-column label="物料编码" width="120" align="center" prop="materialCode" />
<el-table-column label="名称" width="120" align="center" prop="materialName" />
<el-table-column label="材质" width="80" align="center" prop="material" />
<el-table-column label="单重" width="60" align="center" prop="discWeight" />
<el-table-column label="可用库存" align="center" prop="firstBatchQuantity">
<el-table-column label="可用量"width="60" align="center" prop="firstBatchQuantity">
<template slot-scope="scope">
<span :style="{
color: scope.row.firstBatchQuantity > 0 ? 'green' : 'red',
@ -107,34 +107,30 @@
{{ scope.row.firstBatchQuantity }}
</span>
</template>
</el-table-column>
</el-table-column>
<el-table-column label="本批数" width="60" align="center" prop="batchQuantity" />
<!--
<el-table-column label="材料BOM物料编码" width="220"align="center" prop="rawMaterialCode" />
<el-table-column label="材料BOM物料名称"width="220" align="center" prop="rawMaterialName" />
<el-table-column label="用量"width="60"align="center" prop="discUsage" />
<el-table-column label="单位"width="60" align="center" prop="bomUnit" />-->
<el-table-column label="工序号" width="60" align="center" prop="processNo" />
<el-table-column label="工作中心" width="150" align="center">
<el-table-column label="工作中心" width="84" align="center">
<template slot-scope="scope">
<el-form-item v-if="scope.row.isEdit" :prop="'routeList.' + scope.$index + '.workCenter'">
<el-select v-model="scope.row.workCenter" placeholder="工作中心" clearable
@change="() => handleWorkCenterChange(scope)"> <!-- 修改这里 -->
<el-option label="机一工段" value="机一工段"></el-option>
<el-option label="机二工段" value="机二工段"></el-option>
<el-option label="机三工段" value="机三工段"></el-option>
<el-option label="装一工段" value="装一工段"></el-option>
<el-option label="装二工段" value="装二工段"></el-option>
<el-option label="铆焊工段" value="铆焊工段"></el-option>
<el-option label="电钳工段" value="电钳工段"></el-option>
<el-option label="委外中心" value="委外中心"></el-option>
<el-select v-model="scope.row.workCenter" placeholder="请选择工作中心" clearable>
<el-option v-for="dict in dict.type.work_center" :key="dict.value" :label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<span v-else>{{ scope.row.workCenter }}</span>
<span v-else>
<dict-tag :options="dict.type.work_center" :value="scope.row.workCenter" />
</span>
</template>
</el-table-column>
<el-table-column label="工序名称" width="150" align="center">
<el-table-column label="工序名称" width="100" align="center">
<template slot-scope="scope">
<el-form-item v-if="scope.row.id < 0 || scope.row.isEdit"
:prop="'routeList.' + scope.$index + '.processName'">
@ -147,7 +143,7 @@
</template>
</el-table-column>
<el-table-column label="序说明" width="300" align="center">
<el-table-column label="序说明" width="200" align="center">
<template slot-scope="scope">
<el-form-item v-if="scope.row.id < 0 || scope.row.isEdit"
:prop="'routeList.' + scope.$index + '.processDescription'">
@ -158,7 +154,7 @@
</el-table-column>
<!-- 工序控制列 -->
<el-table-column label="工序控制码" width="220" align="center">
<el-table-column label="工序控制码" width="100" align="center">
<template slot-scope="scope">
<el-form-item v-if="scope.row.isEdit" :prop="'routeList.' + scope.$index + '.processControl'">
<el-select v-model="scope.row.processControl" placeholder="请选择工序控制码" clearable>
@ -182,7 +178,7 @@
</el-table-column>
<el-table-column label="活动单位" align="center" prop="activityUnit" />
<el-table-column label="序开始时间" align="center" prop="xuStartTime" width="180">
<el-table-column label="序开始时间" align="center" prop="xuStartTime" width="100">
<template slot-scope="scope">
<el-form-item v-if="scope.row.id < 0 || scope.row.isEdit"
:prop="'routeList.' + scope.$index + '.xuStartTime'">
@ -193,7 +189,7 @@
<span v-else>{{ parseTime(scope.row.xuStartTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="序结束时间" align="center" prop="xuEndTime" width="180">
<el-table-column label="序结束时间" align="center" prop="xuEndTime" width="100">
<template slot-scope="scope">
<el-form-item v-if="scope.row.id < 0 || scope.row.isEdit"
:prop="'routeList.' + scope.$index + '.xuEndTime'">
@ -204,9 +200,8 @@
<span v-else>{{ parseTime(scope.row.xuEndTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="单位" align="center" prop="bomUnit" />
<el-table-column label="单台数量" align="center" prop="unitQuantity" />
<el-table-column label="本批数量" align="center" prop="batchQuantity" />
<!-- //<el-table-column label="" align="center" prop="bomUnit" /> -->
<!-- <el-table-column label="单台数量" align="center" prop="unitQuantity" /> -->
<el-table-column label="计划开始时间" align="center" prop="planStartTime" width="180">
<template slot-scope="scope">
@ -453,7 +448,6 @@
<!-- 搜索和操作按钮 -->
<div class="table-operations" style="margin: 15px 0;">
<div class="right-operations">
<el-button-group>
<el-button type="primary" size="small" @click="handleBomAdd">
@ -498,15 +492,6 @@
</template>
</el-table-column>
</el-table>
<!-- 分页器 -->
<div class="pagination-container" style="margin-top: 15px;">
<el-pagination @size-change="handleBomSizeChange" @current-change="handleBomCurrentChange"
:current-page="bomPagination.currentPage" :page-sizes="[10, 20, 50, 100]"
:page-size="bomPagination.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="totalBomCount">
</el-pagination>
</div>
<!-- BOM编辑对话框 -->
<el-dialog :title="bomDialogTitle" :visible.sync="bomDialogVisible" width="500px" append-to-body>
<el-form ref="bomForm" :model="bomForm" :rules="bomRules" label-width="100px">
@ -571,6 +556,44 @@
<el-button @click="bomDialogVisible = false"> </el-button>
</div>
</el-dialog>
<!-- 工艺路线信息部分 -->
<div class="section-title" style="margin: 20px 0 15px;">
<h3>工艺路线信息</h3>
</div>
<el-table :data="processRoutes" stripe border v-loading="processLoading">
<el-table-column label="工艺编号" prop="fnumber" width="120" align="center" />
<el-table-column label="项目令号" prop="project_code" width="180" align="center" />
<el-table-column label="物料编码" prop="materialCode" width="140" align="center" />
<el-table-column label="物料名称" prop="materialName" min-width="140" align="center" />
<el-table-column label="操作" width="120" align="center">
<template slot-scope="scope">
<el-button type="text" @click="handleViewRoute(scope.row)"
:type="selectedRouteId === scope.row.id ? 'success' : 'primary'">
{{ selectedRouteId === scope.row.id ? '查看中' : '查看' }}
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 选中的工艺路线工序信息 -->
<div v-if="selectedRoute" class="process-detail" style="margin-top: 15px;">
<div class="sub-title" style="margin-bottom: 10px;">
<h4>工序信息 - {{ selectedRoute.fnumber }}</h4>
</div>
<el-table :data="currentProcessList" stripe border max-height="300px">
<el-table-column label="工序号" prop="processNo" width="80" align="center" />
<el-table-column label="工作中心" prop="workCenter" width="120" align="center" />
<el-table-column label="工序名称" prop="processName" width="120" align="center" />
<el-table-column label="工序说明" prop="processDescription" min-width="200" show-overflow-tooltip />
<el-table-column label="工序控制" prop="processControl" width="120" align="center" />
<el-table-column label="活动时长" align="center" width="120">
<template slot-scope="scope">
{{ scope.row.activityDuration }} {{ scope.row.activityUnit }}
</template>
</el-table-column>
</el-table>
</div>
</div>
</el-drawer>
</div>
@ -586,17 +609,18 @@ import {
getDistinctProjectCodes,
updateProcessPlan, generatePDFs, updateBom, addBom, deleteBom
} from "@/api/system/route";
import upload from "svg-sprite-loader/examples/custom-runtime-generator/build/main";
import { getToken } from "../../../utils/auth";
import Fromed from './fromed'
import Bomfrom from './bomfrom'
import { getProcessInfoList, pushRouteBom, onSave, getBomInfo } from "@/api/system/route";
import { getProcessInfoList, pushRouteBom, onSave, getBomInfo, getProcessRouteList } from "@/api/system/route";
import { listMaterial } from "@/api/system/material";
import axios from 'axios';
import dict from "@/utils/dict";
import DictData from "@/components/DictData";
DictData.install();
export default {
name: "",
dicts: ['work_center'],
components: {
Fromed,
Bomfrom
@ -667,6 +691,9 @@ export default {
title: "",
//
open: false,
//
processDetailsVisible: false,
//
//
queryParams: {
pageNum: 1,
@ -865,6 +892,13 @@ export default {
},
materialLoading: false, //
hasMoreMaterial: true, //
activeTab: 'bom', //
processRouteData: [], // 线
processLoading: false, //
processRoutes: [], // 线
selectedRouteId: null, // 线ID
selectedRoute: null, // 线
currentProcessList: [], //
};
},
created() {
@ -901,6 +935,7 @@ export default {
}
},
methods: {
dict,
//
handleWorkCenterChange(scope) {
@ -1190,6 +1225,7 @@ export default {
if (column.property === 'materialCode') {
this.BOMpop = true;
this.bomLoading = true;
this.processLoading = true;
//
this.currentMaterial = {
@ -1216,6 +1252,9 @@ export default {
.finally(() => {
this.bomLoading = false;
});
//
this.getProcessRouteList();
}
},
@ -1498,11 +1537,11 @@ export default {
generatePDFs(rooteProdet)
.then(response => {
let blob = new Blob([response], {type: 'application/zip'})
let blob = new Blob([response], { type: 'application/zip' })
let url = window.URL.createObjectURL(blob)
const link = document.createElement('a') // a
link.href = url
link.download = rooteProdet+'.zip' //
link.download = rooteProdet + '.zip' //
link.click()
URL.revokeObjectURL(url) //
//
@ -1811,8 +1850,62 @@ export default {
});
}
}
},
//
getProcessRouteList() {
this.processLoading = true;
getProcessRouteList(
this.currentMaterial.materialCode,
this.currentMaterial.materialName,
this.currentMaterial.productionOrderNo
)
.then(response => {
this.processRoutes = response || [];
// 线
if (this.processRoutes.length > 0) {
this.handleViewRoute(this.processRoutes[0]);
}
})
.catch(error => {
console.error('获取工艺路线数据失败:', error);
this.$message.error('获取工艺路线数据失败');
this.processRoutes = [];
this.resetRouteSelection();
})
.finally(() => {
this.processLoading = false;
});
},
// 线
handleViewRoute(route) {
this.selectedRouteId = route.id;
this.selectedRoute = route;
this.currentProcessList = route.processRouteDT || [];
},
// 线
resetRouteSelection() {
this.selectedRouteId = null;
this.selectedRoute = null;
this.currentProcessList = [];
}
},
// 线
handleRouteChange(routeId) {
const route = this.processRoutes.find(r => r.id === routeId);
if (route) {
this.selectedRoute = route;
this.currentProcessList = route.processRouteDT || [];
} else {
this.selectedRoute = null;
this.currentProcessList = [];
}
},
};
</script>
<style>

View File

@ -2,42 +2,23 @@
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="物料编码" prop="materialCode">
<el-input
v-model="queryParams.materialCode"
placeholder="请输入物料编码"
clearable
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.materialCode" placeholder="请输入物料编码" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="物料名称" prop="materialName">
<el-input
v-model="queryParams.materialName"
placeholder="请输入物料名称"
clearable
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.materialName" placeholder="请输入物料名称" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="所需库存" prop="requiredStock">
<el-input
v-model="queryParams.requiredStock"
placeholder="请输入所需库存"
clearable
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.requiredStock" placeholder="请输入所需库存" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="当前库存" prop="currentStock">
<el-input
v-model="queryParams.currentStock"
placeholder="请输入当前库存"
clearable
@keyup.enter.native="handleQuery"
/>
<el-input v-model="queryParams.currentStock" placeholder="请输入当前库存" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="触发时间" prop="triggerTime">
<el-date-picker clearable
v-model="queryParams.triggerTime"
type="date"
value-format="yyyy-MM-dd"
<el-date-picker clearable v-model="queryParams.triggerTime" type="date" value-format="yyyy-MM-dd"
placeholder="请选择触发时间">
</el-date-picker>
</el-form-item>
@ -49,64 +30,32 @@
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['system:stockData:add']"
>新增</el-button>
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
v-hasPermi="['system:stockData:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['system:stockData:edit']"
>修改</el-button>
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
v-hasPermi="['system:stockData:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['system:stockData:remove']"
>删除</el-button>
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
v-hasPermi="['system:stockData:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['system:stockData:export']"
>导出</el-button>
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
v-hasPermi="['system:stockData:export']">导出</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="generateDoc"
v-hasPermi="['system:stockData:generateDoc']"
>生成安全库存单据</el-button>
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="generateDoc"
v-hasPermi="['system:stockData:generateDoc']">生成安全库存单据</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="stockDataList" border @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<!-- <el-table-column label="主键ID" align="center" prop="id" v-if="true"/>-->
<el-table-column label="物料编码" align="center" prop="materialCode">
<!-- <el-table-column label="主键ID" align="center" prop="id" v-if="true"/>-->
<el-table-column label="物料编码" align="center" prop="materialCode">
<template slot-scope="scope">
<span :style="{
color: scope.row.availableStock < scope.row.minsafetyStock ? 'red' : 'inherit',
@ -137,31 +86,16 @@
<el-table-column label="单据类型 " align="center" width="200" prop="documentType" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['system:stockData:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['system:stockData:remove']"
>删除</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
v-hasPermi="['system:stockData:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['system:stockData:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
@pagination="getList" />
<!-- 添加或修改安全库存单据对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
@ -179,10 +113,7 @@
<el-input v-model="form.currentStock" placeholder="请输入当前库存" />
</el-form-item>
<el-form-item label="触发时间" prop="triggerTime">
<el-date-picker clearable
v-model="form.triggerTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
<el-date-picker clearable v-model="form.triggerTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择触发时间">
</el-date-picker>
</el-form-item>
@ -192,6 +123,16 @@
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<el-progress :percentage="percentage"></el-progress>
<div class="log-container">
<ul ref="list" class="log-list">
<li v-for="(item, index) in list" :key="index" :class="['log-item', getLogClass(item.message)]">
<span class="log-timestamp">{{ item.timestamp }}</span>
<span class="log-message">{{ item.message }}</span>
</li>
</ul>
</div>
</div>
</template>
@ -202,9 +143,10 @@ import {
delStockData,
addStockData,
updateStockData,
generateDoc
generateDoc,
logs,
fetchLogs
} from "@/api/system/stockData";
import {listRoute} from "@/api/system/route";
export default {
name: "StockData",
@ -278,7 +220,11 @@ export default {
updateBy: [
{ required: true, message: "更新人不能为空", trigger: "blur" }
]
}
},
percentage: 0,
list: [],
lastLogIndex: 0,
timer: null //
};
},
created() {
@ -329,7 +275,7 @@ export default {
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!==1
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
@ -396,27 +342,145 @@ export default {
...this.queryParams
}, `stockData_${new Date().getTime()}.xlsx`)
},
updateProgress() {
if (this.percentage < 100) {
this.percentage++;
this.scrollToBottom();
} else {
this.percentage = 100;
}
},
scrollToBottom() {
this.$nextTick(() => {
const list = this.$refs.list;
list.scrollTop = list.scrollHeight;
});
},
generateDoc() {
this.loading = true;
this.percentage = 0;
this.list = [];
this.timer = setInterval(this.updateProgress, 1000);
this.fetchLogs(); //
generateDoc().then(response => {
this.loading = false;
//
clearInterval(this.timer);
this.percentage = 100;
if (response.code === 200) {
const stockDataList = response.data;
this.list.push('生成安全库存单据成功!');
} else {
this.$message.error('生成安全库存单据失败,请稍后再试');
this.list.push('生成安全库存单据失败');
}
//
this.refreshPage();
})
.catch((error) => {
this.loading = false;
console.error('请求错误:', error);
clearInterval(this.timer);
this.$message.error('请求失败,请检查网络连接');
//
this.list.push('请求失败,请检查网络连接');
this.refreshPage();
});
},
fetchLogs() {
this.timer = setInterval(() => {
console.log('请求日志接口');
logs(this.lastLogIndex)
.then(response => {
console.log('完整响应:', response);
if (Array.isArray(response)) {
const newLogs = response.map(message => ({
timestamp: this.formatTimestamp(new Date()),
message: message
}));
this.list = this.list.concat(newLogs);
console.log('更新后的 list:', this.list);
this.lastLogIndex += response.length;
} else {
console.error('返回的数据格式不正确:', response);
}
this.scrollToBottom();
})
.catch(error => {
console.error('获取日志失败:', error);
});
}, 5000);
},
formatTimestamp(date) {
const year = date.getFullYear();
const month = this.padZero(date.getMonth() + 1);
const day = this.padZero(date.getDate());
const hours = this.padZero(date.getHours());
const minutes = this.padZero(date.getMinutes());
const seconds = this.padZero(date.getSeconds());
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
},
padZero(num) {
return num < 10 ? '0' + num : num;
},
mounted() {
//
this.fetchLogs();
},
beforeDestroy() {
clearInterval(this.timer);
},
getLogClass(message) {
if (message.includes('错误') || message.includes('失败')) {
return 'log-error';
} else if (message.includes('成功')) {
return 'log-success';
} else {
return 'log-info';
}
}
}
};
</script>
<style scoped>
.log-container {
height: 300px;
overflow-y: auto;
border: 1px solid #ccc;
border-radius: 4px;
padding: 10px;
margin-top: 20px;
}
.log-list {
list-style-type: none;
padding: 0;
margin: 0;
}
.log-item {
margin-bottom: 10px;
}
.log-timestamp {
color: #999;
font-size: 12px;
margin-right: 10px;
}
.log-message {
font-size: 14px;
}
.log-error {
color: red;
}
.log-success {
color: green;
}
.log-info {
color: blue;
}
</style>

View File

@ -0,0 +1,492 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="生产订单号" prop="moBillNo">
<el-input
v-model="queryParams.moBillNo"
placeholder="请输入生产订单号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="生产令号" prop="moOrderNo">
<el-input
v-model="queryParams.moOrderNo"
placeholder="请输入生产令号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="产品编码" prop="materialNumber">
<el-input
v-model="queryParams.materialNumber"
placeholder="请输入产品编码"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="产品名称" prop="materialName">
<el-input
v-model="queryParams.materialName"
placeholder="请输入产品名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="生产数量" prop="operQty">
<el-input
v-model="queryParams.operQty"
placeholder="请输入生产数量"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="转入数量" prop="transInQty">
<el-input
v-model="queryParams.transInQty"
placeholder="请输入转入数量"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="转出数量" prop="transOutQty">
<el-input
v-model="queryParams.transOutQty"
placeholder="请输入转出数量"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="物料状态" prop="materialStatus">
<el-select v-model="queryParams.materialStatus" placeholder="请选择物料状态" clearable>
<el-option
v-for="dict in dict.type.work_center"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="工序号" prop="operNumber">
<el-input
v-model="queryParams.operNumber"
placeholder="请输入工序号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="工序名称" prop="processName">
<el-input
v-model="queryParams.processName"
placeholder="请输入工序名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="计划开始时间" prop="operPlanStartTime">
<el-input
v-model="queryParams.operPlanStartTime"
placeholder="请输入计划开始时间"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="计划完成时间" prop="operPlanFinishTime">
<el-input
v-model="queryParams.operPlanFinishTime"
placeholder="请输入计划完成时间"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="延迟天数" prop="delayDays">
<el-input
v-model="queryParams.delayDays"
placeholder="请输入延迟天数"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @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
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['system:workCenterData:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['system:workCenterData:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['system:workCenterData:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['system:workCenterData:export']"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="workCenterDataList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="主键ID" align="center" prop="id" v-if="true"/>
<el-table-column label="生产订单号" align="center" prop="moBillNo" />
<el-table-column label="生产令号" align="center" prop="moOrderNo" />
<el-table-column label="产品编码" align="center" prop="materialNumber" />
<el-table-column label="产品名称" align="center" prop="materialName" />
<el-table-column label="生产数量" align="center" prop="operQty" />
<el-table-column label="转入数量" align="center" prop="transInQty" />
<el-table-column label="转出数量" align="center" prop="transOutQty" />
<el-table-column label="物料状态" align="center" prop="materialStatus">
<template slot-scope="scope">
<dict-tag :options="dict.type.work_center" :value="scope.row.materialStatus"/>
</template>
</el-table-column>
<el-table-column label="工序号" align="center" prop="operNumber" />
<el-table-column label="工序名称" align="center" prop="processName" />
<el-table-column label="计划开始时间" align="center" prop="operPlanStartTime" />
<el-table-column label="计划完成时间" align="center" prop="operPlanFinishTime" />
<el-table-column label="延迟天数" align="center" prop="delayDays" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['system:workCenterData:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['system:workCenterData:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改金蝶工段数据对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="生产订单号" prop="moBillNo">
<el-input v-model="form.moBillNo" placeholder="请输入生产订单号" />
</el-form-item>
<el-form-item label="生产令号" prop="moOrderNo">
<el-input v-model="form.moOrderNo" placeholder="请输入生产令号" />
</el-form-item>
<el-form-item label="产品编码" prop="materialNumber">
<el-input v-model="form.materialNumber" placeholder="请输入产品编码" />
</el-form-item>
<el-form-item label="产品名称" prop="materialName">
<el-input v-model="form.materialName" placeholder="请输入产品名称" />
</el-form-item>
<el-form-item label="生产数量" prop="operQty">
<el-input v-model="form.operQty" placeholder="请输入生产数量" />
</el-form-item>
<el-form-item label="转入数量" prop="transInQty">
<el-input v-model="form.transInQty" placeholder="请输入转入数量" />
</el-form-item>
<el-form-item label="转出数量" prop="transOutQty">
<el-input v-model="form.transOutQty" placeholder="请输入转出数量" />
</el-form-item>
<el-form-item label="物料状态" prop="materialStatus">
<el-radio-group v-model="form.materialStatus">
<el-radio
v-for="dict in dict.type.work_center"
:key="dict.value"
:label="dict.value"
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="工序号" prop="operNumber">
<el-input v-model="form.operNumber" placeholder="请输入工序号" />
</el-form-item>
<el-form-item label="工序名称" prop="processName">
<el-input v-model="form.processName" placeholder="请输入工序名称" />
</el-form-item>
<el-form-item label="计划开始时间" prop="operPlanStartTime">
<el-input v-model="form.operPlanStartTime" placeholder="请输入计划开始时间" />
</el-form-item>
<el-form-item label="计划完成时间" prop="operPlanFinishTime">
<el-input v-model="form.operPlanFinishTime" placeholder="请输入计划完成时间" />
</el-form-item>
<el-form-item label="延迟天数" prop="delayDays">
<el-input v-model="form.delayDays" placeholder="请输入延迟天数" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listWorkCenterData, getWorkCenterData, delWorkCenterData, addWorkCenterData, updateWorkCenterData } from "@/api/system/workCenterData";
export default {
name: "WorkCenterData",
dicts: ['work_center'],
data() {
return {
// loading
buttonLoading: false,
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
workCenterDataList: [],
//
title: "",
//
open: false,
//
queryParams: {
pageNum: 1,
pageSize: 10,
moBillNo: undefined,
moOrderNo: undefined,
materialNumber: undefined,
materialName: undefined,
operQty: undefined,
transInQty: undefined,
transOutQty: undefined,
materialStatus: undefined,
operNumber: undefined,
processName: undefined,
operPlanStartTime: undefined,
operPlanFinishTime: undefined,
delayDays: undefined,
},
//
form: {},
//
rules: {
id: [
{ required: true, message: "主键ID不能为空", trigger: "blur" }
],
moBillNo: [
{ required: true, message: "生产订单号不能为空", trigger: "blur" }
],
moOrderNo: [
{ required: true, message: "生产令号不能为空", trigger: "blur" }
],
materialNumber: [
{ required: true, message: "产品编码不能为空", trigger: "blur" }
],
materialName: [
{ required: true, message: "产品名称不能为空", trigger: "blur" }
],
operQty: [
{ required: true, message: "生产数量不能为空", trigger: "blur" }
],
transInQty: [
{ required: true, message: "转入数量不能为空", trigger: "blur" }
],
transOutQty: [
{ required: true, message: "转出数量不能为空", trigger: "blur" }
],
materialStatus: [
{ required: true, message: "物料状态不能为空", trigger: "change" }
],
operNumber: [
{ required: true, message: "工序号不能为空", trigger: "blur" }
],
processName: [
{ required: true, message: "工序名称不能为空", trigger: "blur" }
],
operPlanStartTime: [
{ required: true, message: "计划开始时间不能为空", trigger: "blur" }
],
operPlanFinishTime: [
{ required: true, message: "计划完成时间不能为空", trigger: "blur" }
],
delayDays: [
{ required: true, message: "延迟天数不能为空", trigger: "blur" }
],
createTime: [
{ required: true, message: "创建时间不能为空", trigger: "blur" }
],
updateTime: [
{ required: true, message: "更新时间不能为空", trigger: "blur" }
]
}
};
},
created() {
this.getList();
},
methods: {
/** 查询金蝶工段数据列表 */
getList() {
this.loading = true;
listWorkCenterData(this.queryParams).then(response => {
this.workCenterDataList = response.rows;
this.total = response.total;
this.loading = false;
});
},
//
cancel() {
this.open = false;
this.reset();
},
//
reset() {
this.form = {
id: undefined,
moBillNo: undefined,
moOrderNo: undefined,
materialNumber: undefined,
materialName: undefined,
operQty: undefined,
transInQty: undefined,
transOutQty: undefined,
materialStatus: undefined,
operNumber: undefined,
processName: undefined,
operPlanStartTime: undefined,
operPlanFinishTime: undefined,
delayDays: undefined,
createBy: undefined,
createTime: undefined,
updateBy: undefined,
updateTime: undefined
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!==1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加金蝶工段数据";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.loading = true;
this.reset();
const id = row.id || this.ids
getWorkCenterData(id).then(response => {
this.loading = false;
this.form = response.data;
this.open = true;
this.title = "修改金蝶工段数据";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
this.buttonLoading = true;
if (this.form.id != null) {
updateWorkCenterData(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
}).finally(() => {
this.buttonLoading = false;
});
} else {
addWorkCenterData(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
}).finally(() => {
this.buttonLoading = false;
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$modal.confirm('是否确认删除金蝶工段数据编号为"' + ids + '"的数据项?').then(() => {
this.loading = true;
return delWorkCenterData(ids);
}).then(() => {
this.loading = false;
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {
}).finally(() => {
this.loading = false;
});
},
/** 导出按钮操作 */
handleExport() {
this.download('system/workCenterData/export', {
...this.queryParams
}, `workCenterData_${new Date().getTime()}.xlsx`)
}
}
};
</script>