2025-12-08 14:16:59 +08:00

409 lines
11 KiB
Vue

<template>
<div class="work-order-page">
<el-row :gutter="20">
<el-col :span="5">
<div class="order-list">
<h3>今日工单列表</h3>
<ul>
<li v-for="(order, index) in orders" style="position: relative;"
@click="onHandleOrderClick(order)" :key="index" :class="{ active: order.active }">
<span>{{ order.workOrderCode }}</span>
<div style="color: #666;font-size: 12px;">
<span>{{ order.lineName }}</span>
<span style="margin-left: 20px;">数量:{{ order.totalQty }}</span>
</div>
<span style="position: absolute; right: 5%; top:35%"
:class="getOrderStatusClass(order.orderStatus)">{{
getOrderStatusText(order.orderStatus) }}</span>
</li>
</ul>
</div>
</el-col>
<el-col :span="15">
<div class="main-content">
<h2>工单号: {{ currentOrder.workOrderCode }}</h2>
<div class="product-info">
<div class="info-item">
<span>产线编号:</span>
<span>{{ currentOrder.lineCode }}</span>
</div>
<div class="info-item">
<span>产线名称:</span>
<span>{{ currentOrder.lineName }}</span>
</div>
<div class="info-item">
<span>工艺路线编码:</span>
<span>{{ currentOrder.processCode }}</span>
</div>
<div class="info-item">
<span>工艺路线名称:</span>
<span>{{ currentOrder.processName }}</span>
</div>
</div>
<div class="order-data">
<div class="data-item">
<span>工单日期:</span>
<span>{{ currentOrder.orderDate }}</span>
</div>
<div class="data-item">
<span>零件编码:</span>
<span>{{ currentOrder.materialCode }}</span>
</div>
<div class="data-item">
<span>工单状态:</span>
<span :class="getOrderStatusClass(currentOrder.orderStatus)">{{
getOrderStatusText(currentOrder.orderStatus)
}}</span>
</div>
<div class="data-item">
<span>零件名称:</span>
<span>{{ currentOrder.materialName }}</span>
</div>
</div>
<div class="remark">
<p>{{ currentOrder.remark }}</p>
</div>
<div class="input-section">
<div class="input-group">
<label>合格数</label>
<input v-model.number="currentOrder.okQty" type="number" />
</div>
<div class="input-group">
<label>不合格数</label>
<input min="0" v-model.number="currentOrder.ngQty" type="number" />
</div>
<div class="input-group">
<label>不良原因</label>
<textarea min="0" v-model="currentOrder.defectReason" placeholder="请输入不良原因"></textarea>
</div>
</div>
<div class="button-group">
<el-button @click="save">保存</el-button>
<el-button type="primary" @click="completeOrder">工单完工</el-button>
</div>
</div>
</el-col>
<el-col :span="4">
<div class="scan-area">
<h3>标签扫描</h3>
<el-form label-width="70px">
<el-form-item label="选择产线">
<el-select filterable clearable @change="handleSelectLineName" v-model="lineName"
placeholder="请选择产线">
<el-option v-for="item in productionLine" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="扫码结果">
<el-input @keyup.enter="handleQuery" placeholder="请扫描或输入"
v-model="tagNumber"></el-input>
</el-form-item>
</el-form>
</div>
</el-col>
</el-row>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { getProcessInfoTree, updateProcessInfo, updateProcessInfoList, checkFirstInspection, getLineName } from '@/api/humanComputerInteraction/index.js';
import { ElMessage } from 'element-plus';
const productionLine = ref([])
const tagNumber = ref('');
import { dayjs } from 'element-plus';
const orders = ref([
]);
const lineName = ref('');
// 当前选中的工单
const currentOrder = ref({
workOrderCode: '',//工单编号
lineCode: '',//产线编号
lineName: '',//产线名称
processCode: '',//工艺路线编码
processName: '',//工艺路线名称
orderDate: '',//工单日期
materialCode: '',//零件编码
materialName: '',//零件名称
okQty: '',//合格数
ngQty: '',//不合格数
defectReason: '',//不良原因描述
totalQty: '',//总数
orderStatus: '',//工单状态
UpdateBy: '',
UpdateName: '',
});
const getLeftTreeList = () => {
getProcessInfoTree().then(res => {
if (res.code == 200) {
orders.value = res.data
}
})
}
getLeftTreeList()
const getLineNameData = () => {
getLineName().then(res => {
if (res.code == 200) {
productionLine.value = res.data.map(item => {
return {
label: item.label,
value: item.value
}
})
}
})
}
getLineNameData()
const getOrderStatusClass = (status) => {
const statusClassMap = {
'0': 'pending',
'1': 'processing',
'2': 'completed'
};
return statusClassMap[status] || '';
};
const getOrderStatusText = (status) => {
const statusMap = {
'0': '待执行',
'1': '执行中',
'2': '已完成'
};
return statusMap[status] || '';
};
const isWhiteText = ref(false)
const onHandleOrderClick = (val) => {
isWhiteText.value = true
orders.value.forEach(order => {
order.active = false;
});
val.active = true;
currentOrder.value = {
...val
}
}
const handleQuery = () => {
if (!lineName.value) {
ElMessage.error('请选择产线名称');
return;
}
let params={
lineCode:lineName.value,
checkDate:dayjs(new Date()).format('YYYY-MM-DD'),
}
checkFirstInspection(params).then(res => {
if (res.code == 400) {
ElMessage.error(res.msg);
return
}
if(res && res.code == 200){
ElMessage.success('请求成功!');
}
})
}
// 保存按钮点击事件
const save = () => {
updateProcessInfo(currentOrder.value).then(res => {
if (res.code == 200) {
ElMessage.success('保存成功')
}
})
};
const completeOrder = () => {
if (currentOrder.value.orderStatus == '2') {
ElMessage.warning('工单已完工,请勿重复操作')
return;
}
let data = {
...currentOrder.value,
orderStatus: currentOrder.value.orderStatus = '2'
}
updateProcessInfoList(data).then(res => {
if (res.code == 200) {
ElMessage.success('状态修改完成')
}
})
};
</script>
<style scoped>
.work-order-page {
padding: 20px;
height: 100%;
background-color: #f5f5f5;
}
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
font-size: 14px;
}
.time {
color: #666;
}
.pending {
color: #999999;
}
.processing {
color: #409EFF;
}
.completed {
color: #4caf50;
}
.order-list {
background: white;
border-radius: 8px;
padding: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.order-list h3 {
margin-top: 0;
color: white;
background-color: #409EFF;
padding: 8px;
border-radius: 4px;
font-size: 14px;
}
.order-list ul {
list-style: none;
padding: 0;
margin: 10px 0;
}
.order-list li {
padding: 8px;
border-bottom: 1px solid #eee;
cursor: pointer;
}
.order-list li:hover {
background-color: #f0f0f0;
}
.order-list li.active {
background-color: #f0f0f0;
color: #000 !important;
}
.order-list .status {
float: right;
padding: 2px 8px;
border-radius: 4px;
font-size: 12px;
}
.white-text {
color: white;
}
.main-content {
background: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.main-content h2 {
margin-top: 0;
color: #333;
font-size: 18px;
}
.info-item,
.data-item {
display: flex;
margin-bottom: 8px;
}
.info-item span:first-child,
.data-item span:first-child {
width: 100px;
font-weight: bold;
color: #666;
}
.info-item span:last-child,
.data-item span:last-child {
flex: 1;
}
.normal {
color: #4caf50;
}
.remark {
margin: 20px 0;
padding: 10px;
background-color: #f9f9f9;
border-radius: 4px;
font-size: 12px;
line-height: 1.5;
}
.input-section {
margin: 20px 0;
}
.input-group {
margin-bottom: 16px;
}
.input-group label {
display: block;
margin-bottom: 8px;
font-weight: bold;
color: #333;
}
.input-group input,
.input-group textarea {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
.button-group {
display: flex;
gap: 16px;
margin-top: 20px;
}
.scan-area {
background: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
text-align: center;
}
.scan-area h3 {
margin-top: 0;
color: #333;
}
.scan-box {
width: 100%;
height: 100px;
background-color: #409EFF;
margin-top: 16px;
border-radius: 4px;
}
</style>