Files
double-rack/ruoyi-ui/src/views/mill/pdo.vue
朱昊天 8ea6894552 工艺管理
修复“重置导致选中丢失”
修复“新增保存后不会停留在新方案”
修复“搜索后左右不同步”
生产计划
定位生产计划页 plan.vue 的查询参数、日期范围、完成按钮与方案下拉逻辑
修复日期范围筛选:前端按后端约定写入 queryParams.params.beginTime/endTime
修复“不显示生产完成”筛选:前后端新增 excludeDone 过滤并落到 SQL 条件
修复完成计划幂等:后端避免重复插入实绩;前端对已完成禁用按钮
生产绩效
修复“明细信息显示旧数据”
修复“点击表格行只看明细但不能直接修改/删除
修复“时间字段时分秒丢失”
 修复“补录/修改表单无校验”
2026-06-16 13:56:58 +08:00

637 lines
26 KiB
Vue

<template>
<div class="app-container">
<el-row :gutter="20">
<el-col :span="24">
<el-card shadow="never">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="成品卷号" prop="exitMatId">
<el-input
v-model="queryParams.exitMatId"
placeholder="请输入成品卷号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="来料卷号" prop="entryMatId">
<el-input
v-model="queryParams.entryMatId"
placeholder="请输入来料卷号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="计划号" prop="planNo">
<el-input
v-model="queryParams.planNo"
placeholder="请输入计划号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="班号" prop="groupNo">
<el-input
v-model="queryParams.groupNo"
placeholder="请输入班号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="组号" prop="shiftNo">
<el-input
v-model="queryParams.shiftNo"
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="['mill:actual: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="['mill:actual: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="['mill:actual: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="['mill:actual:export']"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table ref="actualTable" v-loading="loading" :data="actualList" row-key="actualId" @selection-change="handleSelectionChange" @row-click="handleRowClick" highlight-current-row>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="成品卷号" align="center" prop="exitMatId" />
<el-table-column label="来料卷号" align="center" prop="entryMatId" />
<el-table-column label="计划号" align="center" prop="planNo" />
<el-table-column label="产品类型" align="center" prop="prodCode" />
<el-table-column label="班号" align="center" prop="groupNo" />
<el-table-column label="组号" align="center" prop="shiftNo" />
<el-table-column label="钢种" align="center" prop="steelGrade" />
<el-table-column label="成品厚度" align="center" prop="exitThickness" />
<el-table-column label="成品宽度" align="center" prop="exitWidth" />
<el-table-column label="实际重量" align="center" prop="actualWeight" />
<el-table-column label="上线时间" align="center" prop="onlineTime" width="170">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.onlineTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<!-- <el-table-column label="状态" align="center" prop="status" /> -->
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click.stop="handleUpdate(scope.row)"
v-hasPermi="['mill:actual:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click.stop="handleDelete(scope.row)"
v-hasPermi="['mill:actual: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-card>
</el-col>
</el-row>
<el-row :gutter="20" style="margin-top: 20px;">
<el-col :span="24">
<el-card shadow="never" v-if="currentRow">
<div slot="header" class="clearfix">
<span style="font-size: 16px; font-weight: bold;">明细信息</span>
</div>
<el-descriptions :column="4" border>
<el-descriptions-item label="成品卷号">{{ currentRow.exitMatId }}</el-descriptions-item>
<el-descriptions-item label="来料卷号">{{ currentRow.entryMatId }}</el-descriptions-item>
<el-descriptions-item label="分切数">{{ currentRow.subId }}</el-descriptions-item>
<el-descriptions-item label="开始位置">{{ currentRow.startPosition }}</el-descriptions-item>
<el-descriptions-item label="结束位置">{{ currentRow.endPosition }}</el-descriptions-item>
<el-descriptions-item label="计划id">{{ currentRow.planId }}</el-descriptions-item>
<el-descriptions-item label="计划号">{{ currentRow.planNo }}</el-descriptions-item>
<el-descriptions-item label="产品类型">{{ currentRow.prodCode }}</el-descriptions-item>
<el-descriptions-item label="班号">{{ currentRow.groupNo }}</el-descriptions-item>
<el-descriptions-item label="组号">{{ currentRow.shiftNo }}</el-descriptions-item>
<el-descriptions-item label="状态">{{ currentRow.status }}</el-descriptions-item>
<el-descriptions-item label="钢种">{{ currentRow.steelGrade }}</el-descriptions-item>
<el-descriptions-item label="来料厚度">{{ currentRow.entryThick }}</el-descriptions-item>
<el-descriptions-item label="来料宽度">{{ currentRow.entryWidth }}</el-descriptions-item>
<el-descriptions-item label="来料长度">{{ currentRow.entryLength }}</el-descriptions-item>
<el-descriptions-item label="来料重量">{{ currentRow.entryWeight }}</el-descriptions-item>
<el-descriptions-item label="上表面镀锌量">{{ currentRow.weightTop }}</el-descriptions-item>
<el-descriptions-item label="下表面镀锌量">{{ currentRow.weightBottom }}</el-descriptions-item>
<el-descriptions-item label="成品长度">{{ currentRow.exitLength }}</el-descriptions-item>
<el-descriptions-item label="成品带涂料重量">{{ currentRow.exitNetWeight }}</el-descriptions-item>
<el-descriptions-item label="理论重量">{{ currentRow.theoryWeight }}</el-descriptions-item>
<el-descriptions-item label="实际重量">{{ currentRow.actualWeight }}</el-descriptions-item>
<el-descriptions-item label="成品外径">{{ currentRow.exitOuterDiameter }}</el-descriptions-item>
<el-descriptions-item label="成品厚度">{{ currentRow.exitThickness }}</el-descriptions-item>
<el-descriptions-item label="成品宽度">{{ currentRow.exitWidth }}</el-descriptions-item>
<el-descriptions-item label="客户">{{ currentRow.customer }}</el-descriptions-item>
<el-descriptions-item label="上线时间">{{ parseTime(currentRow.onlineTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</el-descriptions-item>
<el-descriptions-item label="开始时间">{{ parseTime(currentRow.startTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</el-descriptions-item>
<el-descriptions-item label="结束时间">{{ parseTime(currentRow.endTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</el-descriptions-item>
<el-descriptions-item label="机组号">{{ currentRow.unitCode }}</el-descriptions-item>
<el-descriptions-item label="工序号">{{ currentRow.processCode }}</el-descriptions-item>
<el-descriptions-item label="是否尾卷">{{ currentRow.lastFlag === 1 ? '是' : '否' }}</el-descriptions-item>
<el-descriptions-item label="是否分卷">{{ currentRow.separateFlag === 1 ? '是' : '否' }}</el-descriptions-item>
<el-descriptions-item label="计划来源">{{ currentRow.planOrigin }}</el-descriptions-item>
<el-descriptions-item label="锌层厚度">{{ currentRow.zincCoatingThickness }}</el-descriptions-item>
<el-descriptions-item label="入场钢卷号">{{ currentRow.enterCoilNo }}</el-descriptions-item>
<el-descriptions-item label="备注" :span="4">{{ currentRow.remark }}</el-descriptions-item>
</el-descriptions>
</el-card>
<el-card shadow="never" v-else>
<div style="text-align: center; padding: 40px; color: #909399;">
请点击表格行查看明细信息
</div>
</el-card>
</el-col>
</el-row>
<el-dialog :title="title" :visible.sync="open" width="900px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="成品卷号" prop="exitMatId">
<el-input v-model="form.exitMatId" placeholder="请输入成品卷号" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="来料卷号" prop="entryMatId">
<el-input v-model="form.entryMatId" placeholder="请输入来料卷号" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="分切数" prop="subId">
<el-input v-model="form.subId" placeholder="请输入分切数" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="计划号" prop="planNo">
<el-input v-model="form.planNo" placeholder="请输入计划号" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="产品类型" prop="prodCode">
<el-input v-model="form.prodCode" placeholder="请输入产品类型" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="钢种" prop="steelGrade">
<el-input v-model="form.steelGrade" placeholder="请输入钢种" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="班号" prop="groupNo">
<el-input v-model="form.groupNo" placeholder="请输入班号" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="组号" prop="shiftNo">
<el-input v-model="form.shiftNo" placeholder="请输入组号" />
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">来料信息</el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="来料厚度" prop="entryThick">
<el-input v-model="form.entryThick" placeholder="请输入来料厚度" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="来料宽度" prop="entryWidth">
<el-input v-model="form.entryWidth" placeholder="请输入来料宽度" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="来料长度" prop="entryLength">
<el-input v-model="form.entryLength" placeholder="请输入来料长度" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="来料重量" prop="entryWeight">
<el-input v-model="form.entryWeight" placeholder="请输入来料重量" />
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">成品信息</el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="成品厚度" prop="exitThickness">
<el-input v-model="form.exitThickness" placeholder="请输入成品厚度" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="成品宽度" prop="exitWidth">
<el-input v-model="form.exitWidth" placeholder="请输入成品宽度" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="成品长度" prop="exitLength">
<el-input v-model="form.exitLength" placeholder="请输入成品长度" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="成品外径" prop="exitOuterDiameter">
<el-input v-model="form.exitOuterDiameter" placeholder="请输入成品外径" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="成品带涂料重量" prop="exitNetWeight">
<el-input v-model="form.exitNetWeight" placeholder="请输入成品带涂料重量" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="理论重量" prop="theoryWeight">
<el-input v-model="form.theoryWeight" placeholder="请输入理论重量" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="实际重量" prop="actualWeight">
<el-input v-model="form.actualWeight" placeholder="请输入实际重量" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="客户" prop="customer">
<el-input v-model="form.customer" placeholder="请输入客户" />
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">时间信息</el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="上线时间" prop="onlineTime">
<el-date-picker clearable
v-model="form.onlineTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择上线时间"
style="width: 100%;">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="开始时间" prop="startTime">
<el-date-picker clearable
v-model="form.startTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择开始时间"
style="width: 100%;">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="结束时间" prop="endTime">
<el-date-picker clearable
v-model="form.endTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择结束时间"
style="width: 100%;">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="机组号" prop="unitCode">
<el-input v-model="form.unitCode" placeholder="请输入机组号" />
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">其他信息</el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="工序号" prop="processCode">
<el-input v-model="form.processCode" placeholder="请输入工序号" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否尾卷" prop="lastFlag">
<el-switch v-model="form.lastFlag" :active-value="1" :inactive-value="0" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="是否分卷" prop="separateFlag">
<el-switch v-model="form.separateFlag" :active-value="1" :inactive-value="0" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="计划来源" prop="planOrigin">
<el-input v-model="form.planOrigin" placeholder="请输入计划来源" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="锌层厚度" prop="zincCoatingThickness">
<el-input v-model="form.zincCoatingThickness" placeholder="请输入锌层厚度" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="入场钢卷号" prop="enterCoilNo">
<el-input v-model="form.enterCoilNo" placeholder="请输入入场钢卷号" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listActual, getActual, delActual, addActual, updateActual } from "@/api/mill/actual";
export default {
name: "Actual",
data() {
return {
loading: true,
ids: [],
single: true,
multiple: true,
showSearch: true,
total: 0,
actualList: [],
title: "",
open: false,
currentRow: null,
queryParams: {
pageNum: 1,
pageSize: 10,
exitMatId: null,
entryMatId: null,
subId: null,
startPosition: null,
endPosition: null,
planId: null,
planNo: null,
prodCode: null,
groupNo: null,
shiftNo: null,
status: null,
steelGrade: null,
entryThick: null,
entryWidth: null,
entryLength: null,
entryWeight: null,
weightTop: null,
weightBottom: null,
exitLength: null,
exitNetWeight: null,
theoryWeight: null,
actualWeight: null,
exitOuterDiameter: null,
exitThickness: null,
exitWidth: null,
customer: null,
onlineTime: null,
startTime: null,
endTime: null,
unitCode: null,
processCode: null,
planOrigin: null,
zincCoatingThickness: null,
enterCoilNo: null,
},
form: {},
rules: {
exitMatId: [{ required: true, message: '请输入成品卷号', trigger: 'blur' }],
entryMatId: [{ required: true, message: '请输入来料卷号', trigger: 'blur' }],
planNo: [{ required: true, message: '请输入计划号', trigger: 'blur' }],
}
};
},
created() {
this.getList();
},
methods: {
getList() {
this.loading = true;
listActual(this.queryParams).then(response => {
this.actualList = response.rows || [];
this.total = response.total;
this.loading = false;
this.ids = [];
this.single = true;
this.multiple = true;
if (this.$refs.actualTable) this.$refs.actualTable.clearSelection();
if (this.currentRow && this.currentRow.actualId != null) {
const updated = this.actualList.find(r => r.actualId === this.currentRow.actualId);
this.currentRow = updated || null;
}
});
},
cancel() {
this.open = false;
this.reset();
},
reset() {
this.form = {
actualId: null,
exitMatId: null,
entryMatId: null,
subId: null,
startPosition: null,
endPosition: null,
planId: null,
planNo: null,
prodCode: null,
groupNo: null,
shiftNo: null,
status: null,
steelGrade: null,
entryThick: null,
entryWidth: null,
entryLength: null,
entryWeight: null,
weightTop: null,
weightBottom: null,
exitLength: null,
exitNetWeight: null,
theoryWeight: null,
actualWeight: null,
exitOuterDiameter: null,
exitThickness: null,
exitWidth: null,
customer: null,
onlineTime: null,
startTime: null,
endTime: null,
unitCode: null,
processCode: null,
lastFlag: 0,
separateFlag: 0,
planOrigin: null,
zincCoatingThickness: null,
enterCoilNo: null,
createBy: null,
createTime: null,
updateBy: null,
updateTime: null,
remark: null,
delFlag: null
};
this.resetForm("form");
},
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
resetQuery() {
this.resetForm("queryForm");
this.currentRow = null;
this.ids = [];
this.single = true;
this.multiple = true;
if (this.$refs.actualTable) this.$refs.actualTable.clearSelection();
this.handleQuery();
},
handleSelectionChange(selection) {
this.ids = selection.map(item => item.actualId)
this.single = selection.length!==1
this.multiple = !selection.length
},
handleRowClick(row) {
this.currentRow = row;
if (this.$refs.actualTable) {
this.$refs.actualTable.clearSelection();
this.$refs.actualTable.toggleRowSelection(row, true);
}
},
handleAdd() {
this.reset();
this.open = true;
this.title = "添加轧线生产实绩";
},
handleUpdate(row) {
this.reset();
const actualId = row.actualId || this.ids
getActual(actualId).then(response => {
this.form = response.data;
// 确保这两个字段是数字类型
this.form.lastFlag = this.form.lastFlag === 1 || this.form.lastFlag === '1' ? 1 : 0;
this.form.separateFlag = this.form.separateFlag === 1 || this.form.separateFlag === '1' ? 1 : 0;
this.open = true;
this.title = "修改轧线生产实绩";
});
},
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.actualId != null) {
updateActual(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addActual(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
handleDelete(row) {
const actualIds = row.actualId || this.ids;
this.$modal.confirm('是否确认删除轧线生产实绩编号为"' + actualIds + '"的数据项?').then(function() {
return delActual(actualIds);
}).then(() => {
const deleted = String(actualIds).split(',').map(v => Number(v));
if (this.currentRow && deleted.includes(Number(this.currentRow.actualId))) this.currentRow = null;
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
handleExport() {
this.download('mill/actual/export', {
...this.queryParams
}, `actual_${new Date().getTime()}.xlsx`)
}
}
};
</script>