``1123 5
This commit is contained in:
parent
eea371a159
commit
fa512a8bad
@ -16,6 +16,23 @@ export function getOrderPro(id) {
|
|||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取工艺上传日志
|
||||||
|
export function getRouteLog(id) {
|
||||||
|
return request({
|
||||||
|
url: '/system/orderPro/getRouteLog/' + id,
|
||||||
|
method: 'post'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取BOM上传日志
|
||||||
|
export function getBomUploadStatus(projectCode) {
|
||||||
|
return request({
|
||||||
|
url: '/system/details/viewGetBomUploadStatus',
|
||||||
|
method: 'post',
|
||||||
|
params: { rooteProdet: projectCode }
|
||||||
|
})
|
||||||
|
}
|
||||||
export function processList(params) {
|
export function processList(params) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/orderPro/processlist',
|
url: '/system/orderPro/processlist',
|
||||||
|
|||||||
@ -479,6 +479,262 @@
|
|||||||
style="margin-top: 20px; text-align: right;"
|
style="margin-top: 20px; text-align: right;"
|
||||||
/>
|
/>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
<!-- 第四部分 工艺上传日志 -->
|
||||||
|
<el-card shadow="never" style="margin-top: 20px;">
|
||||||
|
<div slot="header" class="clearfix">
|
||||||
|
<span style="font-weight: 600; font-size: 16px;">工艺上传日志</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 概览统计 -->
|
||||||
|
<div style="margin-bottom: 16px; padding: 12px; background: #f5f7fa; border-radius: 4px; display:flex; gap:24px; align-items:center; flex-wrap: wrap;">
|
||||||
|
<div style="display:flex; align-items:center; gap:8px;">
|
||||||
|
<el-tag type="success" size="small">成功</el-tag>
|
||||||
|
<span style="font-weight: 600; color: #67C23A;">{{ processLogCounts.success }}</span>
|
||||||
|
</div>
|
||||||
|
<div style="display:flex; align-items:center; gap:8px;">
|
||||||
|
<el-tag type="warning" size="small">重复</el-tag>
|
||||||
|
<span style="font-weight: 600; color: #E6A23C;">{{ processLogCounts.duplicate }}</span>
|
||||||
|
</div>
|
||||||
|
<div style="display:flex; align-items:center; gap:8px;">
|
||||||
|
<el-tag type="danger" size="small">失败</el-tag>
|
||||||
|
<span style="font-weight: 600; color: #F56C6C;">{{ processLogCounts.failed }}</span>
|
||||||
|
</div>
|
||||||
|
<div style="margin-left:auto; color:#606266; font-size:13px;">
|
||||||
|
<i class="el-icon-time" style="margin-right: 4px;"></i>
|
||||||
|
<span v-if="processUploadLog.time">{{ processUploadLog.time }}</span>
|
||||||
|
<span v-else style="color: #909399;">暂无时间信息</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 拉取按钮 -->
|
||||||
|
<div style="margin-bottom: 16px;">
|
||||||
|
<el-button type="primary" size="small" @click="fetchProcessLog" :loading="processLogLoading" :disabled="!productionObj || !productionObj.id" icon="el-icon-refresh">
|
||||||
|
拉取最新日志
|
||||||
|
</el-button>
|
||||||
|
<el-button size="small" @click="clearProcessLog" icon="el-icon-delete" style="margin-left: 8px;">清空</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 成功上传(结构化显示) -->
|
||||||
|
<div v-if="processUploadLog.successfulRoutes && processUploadLog.successfulRoutes.length" style="margin-bottom: 20px;">
|
||||||
|
<div style="margin-bottom: 12px; padding: 8px 12px; background: #f0f9ff; border-left: 4px solid #67C23A; border-radius: 4px;">
|
||||||
|
<span style="font-weight: 600; color:#67C23A; font-size: 14px;">
|
||||||
|
<i class="el-icon-success" style="margin-right: 6px;"></i>
|
||||||
|
成功上传({{ processUploadLog.successfulRoutes.length }})
|
||||||
|
</span>
|
||||||
|
<span style="margin-left:12px; color:#909399; font-size:12px;">工序行数:{{ successFlatRows.length }}</span>
|
||||||
|
</div>
|
||||||
|
<el-table :data="successFlatPagedRows" size="small" border stripe style="width: 100%;">
|
||||||
|
<el-table-column prop="materialCode" label="物料编码" width="160" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="materialName" label="物料名称" width="180" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="processNo" label="工序号" width="90" align="center"/>
|
||||||
|
<el-table-column prop="workCenter" label="工作中心" width="120" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="processName" label="工序名称" width="120" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="activityUnit" label="工序单位" width="80" align="center"/>
|
||||||
|
<el-table-column prop="processControl" label="工序控制" width="120" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="activityDuration" label="工序时长" width="100" align="center"/>
|
||||||
|
<el-table-column prop="processDescription" label="工序描述" min-width="150" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="processNameDescription" label="材质/备注" width="140" show-overflow-tooltip/>
|
||||||
|
</el-table>
|
||||||
|
<pagination
|
||||||
|
v-show="successFlatRows.length > 0"
|
||||||
|
:total="successFlatRows.length"
|
||||||
|
:page.sync="processSuccessPage.pageNum"
|
||||||
|
:limit.sync="processSuccessPage.pageSize"
|
||||||
|
@pagination="() => {}"
|
||||||
|
style="margin-top: 12px;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 重复 -->
|
||||||
|
<div v-if="processUploadLog.duplicateRoutes && processUploadLog.duplicateRoutes.length" style="margin-bottom: 20px;">
|
||||||
|
<div style="margin-bottom: 12px; padding: 8px 12px; background: #fdf6ec; border-left: 4px solid #E6A23C; border-radius: 4px;">
|
||||||
|
<span style="font-weight: 600; color:#E6A23C; font-size: 14px;">
|
||||||
|
<i class="el-icon-warning" style="margin-right: 6px;"></i>
|
||||||
|
重复({{ processUploadLog.duplicateRoutes.length }})
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 12px; background: #fafafa; border-radius: 4px;">
|
||||||
|
<el-tag
|
||||||
|
v-for="(dup, idx) in processUploadLog.duplicateRoutes"
|
||||||
|
:key="idx"
|
||||||
|
type="warning"
|
||||||
|
size="small"
|
||||||
|
style="margin-right:8px; margin-bottom:8px; padding: 4px 12px;">
|
||||||
|
{{ dup }}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 失败 -->
|
||||||
|
<div v-if="processUploadLog.failedRoutes && processUploadLog.failedRoutes.length">
|
||||||
|
<div style="margin-bottom: 12px; padding: 8px 12px; background: #fef0f0; border-left: 4px solid #F56C6C; border-radius: 4px;">
|
||||||
|
<span style="font-weight: 600; color:#F56C6C; font-size: 14px;">
|
||||||
|
<i class="el-icon-error" style="margin-right: 6px;"></i>
|
||||||
|
失败({{ processUploadLog.failedRoutes.length }})
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<el-table :data="processFailedPagedItems" size="small" border stripe style="width: 100%;">
|
||||||
|
<el-table-column prop="materialCode" label="物料编码" width="160" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="errorMessage" label="错误信息" min-width="200" show-overflow-tooltip>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span style="color: #F56C6C;">{{ scope.row.errorMessage }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<pagination
|
||||||
|
v-show="processUploadLog.failedRoutes && processUploadLog.failedRoutes.length > 0"
|
||||||
|
:total="processUploadLog.failedRoutes.length"
|
||||||
|
:page.sync="processFailedPage.pageNum"
|
||||||
|
:limit.sync="processFailedPage.pageSize"
|
||||||
|
@pagination="() => {}"
|
||||||
|
style="margin-top: 12px;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<el-empty
|
||||||
|
v-if="(!processUploadLog.successfulRoutes || processUploadLog.successfulRoutes.length === 0) && (!processUploadLog.duplicateRoutes || processUploadLog.duplicateRoutes.length === 0) && (!processUploadLog.failedRoutes || processUploadLog.failedRoutes.length === 0)"
|
||||||
|
description="暂无工艺上传日志数据"
|
||||||
|
:image-size="100"
|
||||||
|
style="padding: 40px 0;">
|
||||||
|
</el-empty>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 第五部分 BOM上传日志 -->
|
||||||
|
<el-card shadow="never" style="margin-top: 20px;">
|
||||||
|
<div slot="header" class="clearfix">
|
||||||
|
<span style="font-weight: 600; font-size: 16px;">BOM上传日志</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 概览统计 -->
|
||||||
|
<div style="margin-bottom: 16px; padding: 12px; background: #f5f7fa; border-radius: 4px; display:flex; gap:24px; align-items:center; flex-wrap: wrap;">
|
||||||
|
<div style="display:flex; align-items:center; gap:8px;">
|
||||||
|
<el-tag type="success" size="small">成功</el-tag>
|
||||||
|
<span style="font-weight: 600; color: #67C23A;">{{ bomLogCounts.success }}</span>
|
||||||
|
</div>
|
||||||
|
<div style="display:flex; align-items:center; gap:8px;">
|
||||||
|
<el-tag type="info" size="small">已存在</el-tag>
|
||||||
|
<span style="font-weight: 600; color: #909399;">{{ bomLogCounts.exists }}</span>
|
||||||
|
</div>
|
||||||
|
<div style="display:flex; align-items:center; gap:8px;">
|
||||||
|
<el-tag type="danger" size="small">失败</el-tag>
|
||||||
|
<span style="font-weight: 600; color: #F56C6C;">{{ bomLogCounts.failed }}</span>
|
||||||
|
</div>
|
||||||
|
<div style="margin-left:auto; color:#606266; font-size:13px;">
|
||||||
|
<span>总计:{{ bomLogCounts.total }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 拉取按钮 -->
|
||||||
|
<div style="margin-bottom: 16px;">
|
||||||
|
<el-button type="primary" size="small" @click="fetchBomLog" :loading="bomLogLoading" :disabled="!productionObj || !productionObj.productionOrderNo" icon="el-icon-refresh">
|
||||||
|
拉取最新日志
|
||||||
|
</el-button>
|
||||||
|
<el-button size="small" @click="clearBomLog" icon="el-icon-delete" style="margin-left: 8px;">清空</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 成功上传 -->
|
||||||
|
<div v-if="bomLogCounts.success > 0" style="margin-bottom: 20px;">
|
||||||
|
<div style="margin-bottom: 12px; padding: 8px 12px; background: #f0f9ff; border-left: 4px solid #67C23A; border-radius: 4px;">
|
||||||
|
<span style="font-weight: 600; color:#67C23A; font-size: 14px;">
|
||||||
|
<i class="el-icon-success" style="margin-right: 6px;"></i>
|
||||||
|
成功上传({{ bomLogCounts.success }})
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
:data="bomSuccessPagedItems"
|
||||||
|
size="small"
|
||||||
|
border
|
||||||
|
stripe
|
||||||
|
style="width: 100%;">
|
||||||
|
<el-table-column prop="materialCode" label="物料编码" width="160" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="reason" label="说明" min-width="200" show-overflow-tooltip>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span style="color: #67C23A;">{{ scope.row.reason }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<pagination
|
||||||
|
v-show="bomLogCounts.success > 0"
|
||||||
|
:total="bomLogCounts.success"
|
||||||
|
:page.sync="bomSuccessPage.pageNum"
|
||||||
|
:limit.sync="bomSuccessPage.pageSize"
|
||||||
|
@pagination="() => {}"
|
||||||
|
style="margin-top: 12px;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 已存在 -->
|
||||||
|
<div v-if="bomLogCounts.exists > 0" style="margin-bottom: 20px;">
|
||||||
|
<div style="margin-bottom: 12px; padding: 8px 12px; background: #f4f4f5; border-left: 4px solid #909399; border-radius: 4px;">
|
||||||
|
<span style="font-weight: 600; color:#909399; font-size: 14px;">
|
||||||
|
<i class="el-icon-info" style="margin-right: 6px;"></i>
|
||||||
|
已存在且一致({{ bomLogCounts.exists }})
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
:data="bomExistsPagedItems"
|
||||||
|
size="small"
|
||||||
|
border
|
||||||
|
stripe
|
||||||
|
style="width: 100%;">
|
||||||
|
<el-table-column prop="materialCode" label="物料编码" width="160" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="reason" label="说明" min-width="200" show-overflow-tooltip>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span style="color: #909399;">{{ scope.row.reason }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<pagination
|
||||||
|
v-show="bomLogCounts.exists > 0"
|
||||||
|
:total="bomLogCounts.exists"
|
||||||
|
:page.sync="bomExistsPage.pageNum"
|
||||||
|
:limit.sync="bomExistsPage.pageSize"
|
||||||
|
@pagination="() => {}"
|
||||||
|
style="margin-top: 12px;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 失败 -->
|
||||||
|
<div v-if="bomLogCounts.failed > 0" style="margin-bottom: 20px;">
|
||||||
|
<div style="margin-bottom: 12px; padding: 8px 12px; background: #fef0f0; border-left: 4px solid #F56C6C; border-radius: 4px;">
|
||||||
|
<span style="font-weight: 600; color:#F56C6C; font-size: 14px;">
|
||||||
|
<i class="el-icon-error" style="margin-right: 6px;"></i>
|
||||||
|
失败({{ bomLogCounts.failed }})
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
:data="bomFailedPagedItems"
|
||||||
|
size="small"
|
||||||
|
border
|
||||||
|
stripe
|
||||||
|
style="width: 100%;">
|
||||||
|
<el-table-column prop="materialCode" label="物料编码" width="160" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="reason" label="错误信息" min-width="200" show-overflow-tooltip>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span style="color: #F56C6C;">{{ formatBomErrorReason(scope.row.reason) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<pagination
|
||||||
|
v-show="bomLogCounts.failed > 0"
|
||||||
|
:total="bomLogCounts.failed"
|
||||||
|
:page.sync="bomFailedPage.pageNum"
|
||||||
|
:limit.sync="bomFailedPage.pageSize"
|
||||||
|
@pagination="() => {}"
|
||||||
|
style="margin-top: 12px;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<el-empty
|
||||||
|
v-if="bomLogCounts.total === 0"
|
||||||
|
description="暂无BOM上传日志数据"
|
||||||
|
:image-size="100"
|
||||||
|
style="padding: 40px 0;">
|
||||||
|
</el-empty>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
<!-- 新增/编辑弹窗 -->
|
<!-- 新增/编辑弹窗 -->
|
||||||
<el-dialog
|
<el-dialog
|
||||||
:title="isEditChain ? '编辑销齿链型号' : '新增销齿链型号'"
|
:title="isEditChain ? '编辑销齿链型号' : '新增销齿链型号'"
|
||||||
@ -663,7 +919,9 @@ import {
|
|||||||
delSave,
|
delSave,
|
||||||
uploadPDF,
|
uploadPDF,
|
||||||
exportRoute,
|
exportRoute,
|
||||||
getMRPResults
|
getMRPResults,
|
||||||
|
getRouteLog,
|
||||||
|
getBomUploadStatus
|
||||||
} from "@/api/system/orderPro";
|
} from "@/api/system/orderPro";
|
||||||
import {processList} from "../../../api/system/orderPro";
|
import {processList} from "../../../api/system/orderPro";
|
||||||
import {listRigidChain} from '@/api/system/pcRigidChain';
|
import {listRigidChain} from '@/api/system/pcRigidChain';
|
||||||
@ -843,7 +1101,29 @@ export default {
|
|||||||
dwgUploadUrl: process.env.VUE_APP_BASE_API + '/system/orderPro/uploadDwg',
|
dwgUploadUrl: process.env.VUE_APP_BASE_API + '/system/orderPro/uploadDwg',
|
||||||
uploadHeaders: {
|
uploadHeaders: {
|
||||||
Authorization: 'Bearer ' + getToken()
|
Authorization: 'Bearer ' + getToken()
|
||||||
}
|
},
|
||||||
|
// DWG 上传大小阈值(MB),用于前端预校验与提示
|
||||||
|
dwgMaxSizeMB: 100,
|
||||||
|
// 工艺上传日志
|
||||||
|
processUploadLog: {
|
||||||
|
time: null,
|
||||||
|
successfulRoutes: [],
|
||||||
|
duplicateRoutes: [],
|
||||||
|
failedRoutes: []
|
||||||
|
},
|
||||||
|
processLogLoading: false,
|
||||||
|
// 工艺日志分页
|
||||||
|
processSuccessPage: { pageNum: 1, pageSize: 10 },
|
||||||
|
processFailedPage: { pageNum: 1, pageSize: 10 },
|
||||||
|
// BOM上传日志
|
||||||
|
bomUploadLog: {
|
||||||
|
items: []
|
||||||
|
},
|
||||||
|
bomLogLoading: false,
|
||||||
|
// BOM日志分页
|
||||||
|
bomSuccessPage: { pageNum: 1, pageSize: 10 },
|
||||||
|
bomExistsPage: { pageNum: 1, pageSize: 10 },
|
||||||
|
bomFailedPage: { pageNum: 1, pageSize: 10 }
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@ -872,7 +1152,294 @@ export default {
|
|||||||
// 不是企标时,drawingPath 保持手填内容
|
// 不是企标时,drawingPath 保持手填内容
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
processLogCounts() {
|
||||||
|
const success = Array.isArray(this.processUploadLog?.successfulRoutes) ? this.processUploadLog.successfulRoutes.length : 0;
|
||||||
|
const duplicate = Array.isArray(this.processUploadLog?.duplicateRoutes) ? this.processUploadLog.duplicateRoutes.length : 0;
|
||||||
|
const failed = Array.isArray(this.processUploadLog?.failedRoutes) ? this.processUploadLog.failedRoutes.length : 0;
|
||||||
|
return {success, duplicate, failed};
|
||||||
|
},
|
||||||
|
successFlatRows() {
|
||||||
|
const rows = [];
|
||||||
|
const list = this.processUploadLog?.successfulRoutes || [];
|
||||||
|
list.forEach(item => {
|
||||||
|
const base = {
|
||||||
|
materialCode: item.materialCode || '',
|
||||||
|
materialName: item.materialName || ''
|
||||||
|
};
|
||||||
|
const details = Array.isArray(item.processRouteDT) ? item.processRouteDT : [];
|
||||||
|
details.forEach(dt => {
|
||||||
|
// 兼容两种字段命名:
|
||||||
|
// 1) 我们的前端命名:processNo / workCenter / processName / activityUnit / processControl / activityDuration / processDescription / processNameDescription
|
||||||
|
// 2) 后端K3字段命名:FOperNumber / FWorkCenterId.FName / FProcessId.FName / FActivity1UnitID.FName / FOptCtrlCodeId.FName / FActivity1Qty / FOperDescription / FNumber
|
||||||
|
const processNo = dt.processNo ?? dt.FOperNumber ?? dt['FOperNumber'];
|
||||||
|
const workCenter = dt.workCenter ?? (dt.FWorkCenterId && dt.FWorkCenterId.FName) ?? dt['FWorkCenterId.FName'];
|
||||||
|
const processName = dt.processName ?? (dt.FProcessId && dt.FProcessId.FName) ?? dt['FProcessId.FName'];
|
||||||
|
const activityUnit = dt.activityUnit ?? (dt.FActivity1UnitID && dt.FActivity1UnitID.FName) ?? dt['FActivity1UnitID.FName'];
|
||||||
|
const processControl = dt.processControl ?? (dt.FOptCtrlCodeId && dt.FOptCtrlCodeId.FName) ?? dt['FOptCtrlCodeId.FName'];
|
||||||
|
const activityDuration = dt.activityDuration ?? dt.FActivity1Qty ?? dt['FActivity1Qty'];
|
||||||
|
const processDescription = dt.processDescription ?? dt.FOperDescription ?? dt['FOperDescription'];
|
||||||
|
const processNameDescription = dt.processNameDescription ?? dt.FNumber ?? dt['FNumber'];
|
||||||
|
rows.push({
|
||||||
|
...base,
|
||||||
|
processNo,
|
||||||
|
workCenter,
|
||||||
|
processName,
|
||||||
|
activityUnit,
|
||||||
|
processControl,
|
||||||
|
activityDuration,
|
||||||
|
processDescription,
|
||||||
|
processNameDescription
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return rows;
|
||||||
|
},
|
||||||
|
// 工艺成功项(分页)
|
||||||
|
successFlatPagedRows() {
|
||||||
|
const rows = this.successFlatRows;
|
||||||
|
const start = (this.processSuccessPage.pageNum - 1) * this.processSuccessPage.pageSize;
|
||||||
|
const end = start + this.processSuccessPage.pageSize;
|
||||||
|
return rows.slice(start, end);
|
||||||
|
},
|
||||||
|
// 工艺失败项(分页)
|
||||||
|
processFailedPagedItems() {
|
||||||
|
const items = Array.isArray(this.processUploadLog?.failedRoutes) ? this.processUploadLog.failedRoutes : [];
|
||||||
|
const start = (this.processFailedPage.pageNum - 1) * this.processFailedPage.pageSize;
|
||||||
|
const end = start + this.processFailedPage.pageSize;
|
||||||
|
return items.slice(start, end);
|
||||||
|
},
|
||||||
|
// BOM上传日志统计
|
||||||
|
bomLogCounts() {
|
||||||
|
const items = Array.isArray(this.bomUploadLog?.items) ? this.bomUploadLog.items : [];
|
||||||
|
const success = items.filter(item => item.code === '200').length;
|
||||||
|
const exists = items.filter(item => item.code === '100').length;
|
||||||
|
const failed = items.filter(item => item.code === '300' || (item.code !== '200' && item.code !== '100')).length;
|
||||||
|
return {
|
||||||
|
success,
|
||||||
|
exists,
|
||||||
|
failed,
|
||||||
|
total: items.length
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// BOM成功项
|
||||||
|
bomSuccessItems() {
|
||||||
|
const items = Array.isArray(this.bomUploadLog?.items) ? this.bomUploadLog.items : [];
|
||||||
|
return items.filter(item => item.code === '200');
|
||||||
|
},
|
||||||
|
// BOM已存在项
|
||||||
|
bomExistsItems() {
|
||||||
|
const items = Array.isArray(this.bomUploadLog?.items) ? this.bomUploadLog.items : [];
|
||||||
|
return items.filter(item => item.code === '100');
|
||||||
|
},
|
||||||
|
// BOM失败项
|
||||||
|
bomFailedItems() {
|
||||||
|
const items = Array.isArray(this.bomUploadLog?.items) ? this.bomUploadLog.items : [];
|
||||||
|
return items.filter(item => item.code === '300' || (item.code !== '200' && item.code !== '100'));
|
||||||
|
},
|
||||||
|
// BOM成功项(分页)
|
||||||
|
bomSuccessPagedItems() {
|
||||||
|
const items = this.bomSuccessItems;
|
||||||
|
const start = (this.bomSuccessPage.pageNum - 1) * this.bomSuccessPage.pageSize;
|
||||||
|
const end = start + this.bomSuccessPage.pageSize;
|
||||||
|
return items.slice(start, end);
|
||||||
|
},
|
||||||
|
// BOM已存在项(分页)
|
||||||
|
bomExistsPagedItems() {
|
||||||
|
const items = this.bomExistsItems;
|
||||||
|
const start = (this.bomExistsPage.pageNum - 1) * this.bomExistsPage.pageSize;
|
||||||
|
const end = start + this.bomExistsPage.pageSize;
|
||||||
|
return items.slice(start, end);
|
||||||
|
},
|
||||||
|
// BOM失败项(分页)
|
||||||
|
bomFailedPagedItems() {
|
||||||
|
const items = this.bomFailedItems;
|
||||||
|
const start = (this.bomFailedPage.pageNum - 1) * this.bomFailedPage.pageSize;
|
||||||
|
const end = start + this.bomFailedPage.pageSize;
|
||||||
|
return items.slice(start, end);
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
async fetchProcessLog() {
|
||||||
|
if (!this.productionObj || !this.productionObj.id) {
|
||||||
|
this.$message.error('请先选择生产令号');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.processLogLoading = true;
|
||||||
|
try {
|
||||||
|
const res = await getRouteLog(this.productionObj.id);
|
||||||
|
if (res && (res.code === 200 || res.success)) {
|
||||||
|
// 后端返回的数据在 msg 字段中(JSON 字符串),如果 msg 为空则尝试 data
|
||||||
|
const jsonStr = res.msg || res.data || '';
|
||||||
|
|
||||||
|
// 如果返回的字符串为空,提示无数据
|
||||||
|
if (!jsonStr || !jsonStr.trim()) {
|
||||||
|
this.$message.info('暂无工艺上传日志');
|
||||||
|
this.clearProcessLog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析 JSON 字符串
|
||||||
|
let parsed = null;
|
||||||
|
try {
|
||||||
|
parsed = JSON.parse(jsonStr);
|
||||||
|
} catch (parseError) {
|
||||||
|
console.error('JSON 解析失败', parseError);
|
||||||
|
this.$message.error('日志数据格式错误,无法解析');
|
||||||
|
this.clearProcessLog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理不同的数据格式
|
||||||
|
let latest = null;
|
||||||
|
|
||||||
|
// 如果是数组,选择时间最新的一条记录
|
||||||
|
if (Array.isArray(parsed)) {
|
||||||
|
if (parsed.length === 0) {
|
||||||
|
this.$message.info('暂无工艺上传日志');
|
||||||
|
this.clearProcessLog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
latest = parsed.reduce((acc, cur) => {
|
||||||
|
const accTime = acc && acc.time ? new Date(acc.time).getTime() : 0;
|
||||||
|
const curTime = cur && cur.time ? new Date(cur.time).getTime() : 0;
|
||||||
|
return curTime >= accTime ? cur : acc;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 如果是单个对象,直接使用
|
||||||
|
else if (parsed && typeof parsed === 'object') {
|
||||||
|
latest = parsed;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.$message.error('日志数据格式不正确');
|
||||||
|
this.clearProcessLog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!latest) {
|
||||||
|
this.$message.info('暂无工艺上传日志');
|
||||||
|
this.clearProcessLog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 直接使用解析后的数据结构
|
||||||
|
// 处理时间:dayjs 支持时间戳(毫秒)和日期字符串
|
||||||
|
this.processUploadLog = {
|
||||||
|
time: latest.time ? dayjs(latest.time).format('YYYY-MM-DD HH:mm:ss') : null,
|
||||||
|
successfulRoutes: latest.successfulRoutes || [],
|
||||||
|
duplicateRoutes: latest.duplicateRoutes || [],
|
||||||
|
failedRoutes: latest.failedRoutes || []
|
||||||
|
};
|
||||||
|
this.$message.success('已拉取最新日志');
|
||||||
|
} else {
|
||||||
|
this.$message.error(res && res.msg ? res.msg : '获取工艺上传日志失败');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('获取工艺上传日志异常', e);
|
||||||
|
this.$message.error('获取工艺上传日志失败');
|
||||||
|
} finally {
|
||||||
|
this.processLogLoading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clearProcessLog() {
|
||||||
|
this.processUploadLog = {
|
||||||
|
time: null,
|
||||||
|
successfulRoutes: [],
|
||||||
|
duplicateRoutes: [],
|
||||||
|
failedRoutes: []
|
||||||
|
};
|
||||||
|
// 重置分页
|
||||||
|
this.processSuccessPage = { pageNum: 1, pageSize: 10 };
|
||||||
|
this.processFailedPage = { pageNum: 1, pageSize: 10 };
|
||||||
|
},
|
||||||
|
// 获取BOM上传日志
|
||||||
|
async fetchBomLog() {
|
||||||
|
if (!this.productionObj || !this.productionObj.productionOrderNo) {
|
||||||
|
this.$message.error('请先选择生产令号');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.bomLogLoading = true;
|
||||||
|
try {
|
||||||
|
const res = await getBomUploadStatus(this.productionObj.productionOrderNo);
|
||||||
|
if (res && (res.code === 200 || res.success)) {
|
||||||
|
// 后端返回的数据在 data 字段中(JSON 字符串),如果 data 为空则尝试 msg
|
||||||
|
const jsonStr = res.data || res.msg || '';
|
||||||
|
|
||||||
|
// 如果返回的字符串为空,提示无数据
|
||||||
|
if (!jsonStr || !jsonStr.trim()) {
|
||||||
|
this.$message.info('暂无BOM上传日志');
|
||||||
|
this.clearBomLog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析 JSON 字符串
|
||||||
|
let parsed = null;
|
||||||
|
try {
|
||||||
|
parsed = JSON.parse(jsonStr);
|
||||||
|
} catch (parseError) {
|
||||||
|
console.error('JSON 解析失败', parseError);
|
||||||
|
this.$message.error('BOM日志数据格式错误,无法解析');
|
||||||
|
this.clearBomLog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理数据:如果是数组,直接使用;如果是对象且有 items 属性,使用 items
|
||||||
|
let items = [];
|
||||||
|
if (Array.isArray(parsed)) {
|
||||||
|
items = parsed;
|
||||||
|
} else if (parsed && typeof parsed === 'object' && Array.isArray(parsed.items)) {
|
||||||
|
items = parsed.items;
|
||||||
|
} else {
|
||||||
|
this.$message.error('BOM日志数据格式不正确');
|
||||||
|
this.clearBomLog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.bomUploadLog = {
|
||||||
|
items: items
|
||||||
|
};
|
||||||
|
this.$message.success('已拉取最新BOM日志');
|
||||||
|
} else {
|
||||||
|
this.$message.error(res && res.msg ? res.msg : '获取BOM上传日志失败');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('获取BOM上传日志异常', e);
|
||||||
|
this.$message.error('获取BOM上传日志失败');
|
||||||
|
} finally {
|
||||||
|
this.bomLogLoading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 清空BOM日志
|
||||||
|
clearBomLog() {
|
||||||
|
this.bomUploadLog = {
|
||||||
|
items: []
|
||||||
|
};
|
||||||
|
// 重置分页
|
||||||
|
this.bomSuccessPage = { pageNum: 1, pageSize: 10 };
|
||||||
|
this.bomExistsPage = { pageNum: 1, pageSize: 10 };
|
||||||
|
this.bomFailedPage = { pageNum: 1, pageSize: 10 };
|
||||||
|
},
|
||||||
|
// 格式化BOM错误信息
|
||||||
|
formatBomErrorReason(reason) {
|
||||||
|
if (!reason) return '';
|
||||||
|
// 如果 reason 是 JSON 字符串,尝试解析并格式化
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(reason);
|
||||||
|
if (Array.isArray(parsed)) {
|
||||||
|
return parsed.map(item => {
|
||||||
|
const field = item.FieldName || '';
|
||||||
|
const message = item.Message || '';
|
||||||
|
return field ? `${field}: ${message}` : message;
|
||||||
|
}).join('; ');
|
||||||
|
}
|
||||||
|
return reason;
|
||||||
|
} catch (e) {
|
||||||
|
// 如果不是 JSON,直接返回原字符串
|
||||||
|
return reason;
|
||||||
|
}
|
||||||
|
},
|
||||||
formatFraction(value) {
|
formatFraction(value) {
|
||||||
// 如果本身就是分数字符串,直接返回
|
// 如果本身就是分数字符串,直接返回
|
||||||
if (typeof value === 'string' && value.includes('/')) {
|
if (typeof value === 'string' && value.includes('/')) {
|
||||||
@ -932,6 +1499,14 @@ export default {
|
|||||||
this.drawer = true;
|
this.drawer = true;
|
||||||
// 打开抽屉后加载表格数据
|
// 打开抽屉后加载表格数据
|
||||||
this.loadChainTableData();
|
this.loadChainTableData();
|
||||||
|
// 自动加载工艺上传日志
|
||||||
|
if (row && row.id) {
|
||||||
|
this.fetchProcessLog();
|
||||||
|
}
|
||||||
|
// 自动加载BOM上传日志
|
||||||
|
if (row && row.productionOrderNo) {
|
||||||
|
this.fetchBomLog();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/** 获取图纸类型标签 */
|
/** 获取图纸类型标签 */
|
||||||
getDrawingTypeLabel(value) {
|
getDrawingTypeLabel(value) {
|
||||||
@ -1560,10 +2135,12 @@ export default {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证文件大小(可选,限制为50MB)
|
// 验证文件大小(根据前端阈值,默认 100MB),提示包含所选文件大小
|
||||||
const maxSize = 50 * 1024 * 1024; // 50MB
|
const limitMB = Number(this.dwgMaxSizeMB) || 100;
|
||||||
|
const maxSize = limitMB * 1024 * 1024;
|
||||||
|
const sizeMB = (file.size / (1024 * 1024)).toFixed(2);
|
||||||
if (file.size > maxSize) {
|
if (file.size > maxSize) {
|
||||||
this.$message.error('文件大小不能超过50MB');
|
this.$message.error(`文件过大(所选 ${sizeMB}MB,限制 ${limitMB}MB)。请压缩后重试或联系管理员调整服务器限制`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1585,6 +2162,11 @@ export default {
|
|||||||
},
|
},
|
||||||
handleDwgUploadError(error, file, row) {
|
handleDwgUploadError(error, file, row) {
|
||||||
console.error('图纸上传失败:', error);
|
console.error('图纸上传失败:', error);
|
||||||
|
const status = (error && (error.status || (error.response && error.response.status))) || 0;
|
||||||
|
if (status === 413) {
|
||||||
|
this.$message.error('文件过大(超出服务器限制)。请联系管理员提高上传大小限制或压缩文件后重试');
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.$message.error(`图纸上传失败:${file.name}`);
|
this.$message.error(`图纸上传失败:${file.name}`);
|
||||||
},
|
},
|
||||||
downloadPDF() {
|
downloadPDF() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user