Browse Source

机加工环节再加个“机加工检验”报工

机加工的生产报工与机加工检验报工也有先后顺序
master
han\hanst 4 weeks ago
parent
commit
2a3bc30974
  1. 277
      src/views/modules/longtron/production-plan-machining-task.vue
  2. 52
      src/views/modules/longtron/production-plan-renovation-order.vue
  3. 35
      src/views/modules/longtron/production-work-report.vue
  4. 10
      src/views/modules/longtron/screen-renovation-progress.vue
  5. 21
      src/views/modules/sys/role-add-or-update.vue
  6. 18
      src/views/modules/sys/role.vue

277
src/views/modules/longtron/production-plan-machining-task.vue

@ -213,10 +213,37 @@
</el-footer> </el-footer>
</el-dialog> </el-dialog>
<el-dialog title="机加工生产报工" :visible.sync="setUp.reportFlag" width="460px" :close-on-click-modal="false" v-drag>
<el-dialog title="机加工节点报工" :visible.sync="setUp.reportFlag" width="460px" :close-on-click-modal="false" @close="handleReportDialogClose" v-drag>
<el-form :model="reportData" label-width="110px" label-position="top"> <el-form :model="reportData" label-width="110px" label-position="top">
<el-form-item label="任务单号"><el-input v-model="reportData.taskNo" disabled></el-input></el-form-item> <el-form-item label="任务单号"><el-input v-model="reportData.taskNo" disabled></el-input></el-form-item>
<el-form-item label="本次报工数量"><el-input v-model="reportData.reportQty" :min="1" :max="999999" style="width: 100%"></el-input></el-form-item>
<el-form-item label="报工节点">
<el-select v-model="reportData.nodeCode" placeholder="请选择节点" style="width: 100%" @change="handleReportNodeChange">
<el-option v-for="item in reportNodeOptions" :key="item.nodeCode" :label="item.nodeName" :value="item.nodeCode"></el-option>
</el-select>
</el-form-item>
<el-form-item v-if="isMachiningProductionNode(reportData.nodeCode)" label="本次报工数量">
<el-input v-model="reportData.reportQty" :min="1" :max="999999" style="width: 100%"></el-input>
</el-form-item>
<el-form-item v-if="isMachiningInspectionNode(reportData.nodeCode)" label="检验影像上传">
<div class="inspection-upload-wrap">
<el-button plain type="primary" size="mini" @click="triggerInspectionImagePicker">选择图片</el-button>
<span class="inspection-upload-tip">支持图片格式可多选上传</span>
<input
ref="inspectionImageInput"
class="inspection-file-input"
type="file"
accept="image/*"
multiple
@change="handleInspectionImageSelect">
<div v-if="inspectionImageList.length > 0" class="inspection-file-list">
<div v-for="(item, index) in inspectionImageList" :key="item.uid" class="inspection-file-item">
<span class="inspection-file-name">{{ item.name }}</span>
<el-button type="text" style="color:#F56C6C" @click="removeInspectionImage(index)">删除</el-button>
</div>
</div>
<div v-else class="inspection-upload-empty">请至少上传1张检验图片</div>
</div>
</el-form-item>
<el-form-item label="报工备注"><el-input v-model="reportData.remark" type="textarea" :rows="2"></el-input></el-form-item> <el-form-item label="报工备注"><el-input v-model="reportData.remark" type="textarea" :rows="2"></el-input></el-form-item>
</el-form> </el-form>
<el-footer style="height: 40px; margin-top: 50px; text-align: center"> <el-footer style="height: 40px; margin-top: 50px; text-align: center">
@ -245,7 +272,7 @@
<el-dialog <el-dialog
title="报工影像文件" title="报工影像文件"
:visible.sync="mediaDialogVisible" :visible.sync="mediaDialogVisible"
width="600px"
width="680px"
:close-on-click-modal="false" :close-on-click-modal="false"
@close="handleMediaDialogClose" @close="handleMediaDialogClose"
v-drag> v-drag>
@ -293,7 +320,7 @@
<el-table-column label="上传时间" min-width="170" align="center"> <el-table-column label="上传时间" min-width="170" align="center">
<template slot-scope="scope">{{ scope.row.createDate || '-' }}</template> <template slot-scope="scope">{{ scope.row.createDate || '-' }}</template>
</el-table-column> </el-table-column>
<el-table-column label="操作" width="90" align="center">
<el-table-column label="操作" width="60" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
type="text" type="text"
@ -338,7 +365,7 @@
</template> </template>
<script> <script>
import { deleteMachiningTask, finishMachiningTask, getMachiningTaskList, getNodeAssigneeList, getNodeAssigneeUsers, getReportLogList, reportMachiningTaskNode, saveMachiningTask, saveNodeAssignee } from '@/api/longchuang/productionPlan'
import { deleteMachiningTask, finishMachiningTask, getMachiningTaskList, getNodeAssigneeList, getNodeAssigneeUsers, getReportLogList, reportMachiningTaskNode, reportWorkNodeWithMedia, saveMachiningTask, saveNodeAssignee } from '@/api/longchuang/productionPlan'
import { getOssVideoStreamUrl, previewOssFileById2, queryOssFilePlus, removeOss } from '@/api/oss/oss' import { getOssVideoStreamUrl, previewOssFileById2, queryOssFilePlus, removeOss } from '@/api/oss/oss'
export default { export default {
@ -348,6 +375,8 @@ export default {
searchData: { modelNo: '', materialName: '', materialSpec: '', status: '', planStartDate: '', planEndDate: '', page: 1, limit: 20 }, searchData: { modelNo: '', materialName: '', materialSpec: '', status: '', planStartDate: '', planEndDate: '', page: 1, limit: 20 },
saveHeaderData: {}, saveHeaderData: {},
reportData: { orderNo: '', taskNo: '', nodeCode: 'machiningProduction', reportQty: '', remark: '' }, reportData: { orderNo: '', taskNo: '', nodeCode: 'machiningProduction', reportQty: '', remark: '' },
reportNodeOptions: [],
inspectionImageList: [],
setUp: { reviewFlag: false, reportFlag: false, assignFlag: false, saveButton: false, reportButton: false, assignButton: false }, setUp: { reviewFlag: false, reportFlag: false, assignFlag: false, saveButton: false, reportButton: false, assignButton: false },
dataList: [], dataList: [],
currentAssignOrder: { orderNo: '', orderType: 'MACHINING' }, currentAssignOrder: { orderNo: '', orderType: 'MACHINING' },
@ -400,7 +429,19 @@ export default {
const done = list.filter(item => item.status === '已完成').length const done = list.filter(item => item.status === '已完成').length
const currentNode = (list.find(item => item.status !== '已完成') || {}).nodeName || '全部完成' const currentNode = (list.find(item => item.status !== '已完成') || {}).nodeName || '全部完成'
const assigneeSummary = list.filter(item => item.assigneeUserName).map(item => `${item.nodeName}:${item.assigneeUserName}`).join(';') const assigneeSummary = list.filter(item => item.assigneeUserName).map(item => `${item.nodeName}:${item.assigneeUserName}`).join(';')
return { ...row, autoAssignAllUsers: !!row.autoAssignAllUsers, nodeReportMode: row.nodeReportMode || 'PARALLEL', nodeList: list, nodeDoneCount: done, nodeTotalCount: list.length, currentNode: row.currentNode || currentNode, reportQty: row.reportQty || 0, assigneeSummary: assigneeSummary || '-' }
return { ...row, autoAssignAllUsers: !!row.autoAssignAllUsers, nodeReportMode: row.nodeReportMode || 'SEQUENTIAL', nodeList: list, nodeDoneCount: done, nodeTotalCount: list.length, currentNode: row.currentNode || currentNode, reportQty: row.reportQty || 0, assigneeSummary: assigneeSummary || '-' }
},
getMachiningDefaultNodeList() {
return [
{ nodeCode: 'machiningProduction', nodeName: '机加工生产', status: '未开始' },
{ nodeCode: 'machiningInspection', nodeName: '机加工检验', status: '未开始' }
]
},
isMachiningProductionNode(nodeCode) {
return nodeCode === 'machiningProduction'
},
isMachiningInspectionNode(nodeCode) {
return nodeCode === 'machiningInspection'
}, },
loadMockData() { loadMockData() {
this.dataList = [ this.dataList = [
@ -413,12 +454,13 @@ export default {
taskQty: 120, taskQty: 120,
reportQty: 30, reportQty: 30,
autoAssignAllUsers: true, autoAssignAllUsers: true,
nodeReportMode: 'PARALLEL',
nodeReportMode: 'SEQUENTIAL',
planFinishDate: '2026-05-25', planFinishDate: '2026-05-25',
finishDate: '', finishDate: '',
status: '进行中', status: '进行中',
nodeList: [ nodeList: [
{ nodeCode: 'machiningProduction', nodeName: '机加工生产', status: '进行中' }
{ nodeCode: 'machiningProduction', nodeName: '机加工生产', status: '已完成' },
{ nodeCode: 'machiningInspection', nodeName: '机加工检验', status: '进行中' }
] ]
}, },
{ {
@ -430,13 +472,11 @@ export default {
taskQty: 240, taskQty: 240,
reportQty: 0, reportQty: 0,
autoAssignAllUsers: true, autoAssignAllUsers: true,
nodeReportMode: 'PARALLEL',
nodeReportMode: 'SEQUENTIAL',
planFinishDate: '2026-05-27', planFinishDate: '2026-05-27',
finishDate: '', finishDate: '',
status: '已排产', status: '已排产',
nodeList: [
{ nodeCode: 'machiningProduction', nodeName: '机加工生产', status: '未开始' }
]
nodeList: this.getMachiningDefaultNodeList()
} }
].map(this.normalizeRow) ].map(this.normalizeRow)
this.totalPage = this.dataList.length this.totalPage = this.dataList.length
@ -489,8 +529,8 @@ export default {
if (row.action && row.action !== '报工完成') { if (row.action && row.action !== '报工完成') {
return false return false
} }
const codeSet = ['machiningProduction']
const nameSet = ['机加工生产']
const codeSet = ['machiningInspection']
const nameSet = ['机加工检验', '检验']
const nodeCode = String(row.nodeCode || '').trim() const nodeCode = String(row.nodeCode || '').trim()
const nodeName = String(row.nodeName || '').replace(/\s+/g, '') const nodeName = String(row.nodeName || '').replace(/\s+/g, '')
return codeSet.includes(nodeCode) || nameSet.some(item => item.replace(/\s+/g, '') === nodeName) return codeSet.includes(nodeCode) || nameSet.some(item => item.replace(/\s+/g, '') === nodeName)
@ -744,8 +784,8 @@ export default {
}, },
openEditDialog(row) { openEditDialog(row) {
this.saveHeaderData = row this.saveHeaderData = row
? { ...row, autoAssignAllUsers: !!row.autoAssignAllUsers, nodeReportMode: row.nodeReportMode || 'PARALLEL' }
: { orderNo: '', modelNo: '', materialName: '', materialSpec: '', taskQty: 1, reportQty: 0, planFinishDate: '', status: '已排产', autoAssignAllUsers: true, nodeReportMode: 'PARALLEL', nodeList: [] }
? { ...row, autoAssignAllUsers: !!row.autoAssignAllUsers, nodeReportMode: row.nodeReportMode || 'SEQUENTIAL' }
: { orderNo: '', modelNo: '', materialName: '', materialSpec: '', taskQty: 1, reportQty: 0, planFinishDate: '', status: '已排产', autoAssignAllUsers: true, nodeReportMode: 'SEQUENTIAL', nodeList: [] }
this.setUp.reviewFlag = true this.setUp.reviewFlag = true
}, },
saveTask() { saveTask() {
@ -759,7 +799,7 @@ export default {
projectNo: this.saveHeaderData.modelNo, projectNo: this.saveHeaderData.modelNo,
nodeList: this.saveHeaderData.nodeList && this.saveHeaderData.nodeList.length nodeList: this.saveHeaderData.nodeList && this.saveHeaderData.nodeList.length
? this.saveHeaderData.nodeList ? this.saveHeaderData.nodeList
: [{ nodeCode: 'machiningProduction', nodeName: '机加工生产', status: '未开始' }]
: this.getMachiningDefaultNodeList()
} }
this.setUp.saveButton = true this.setUp.saveButton = true
saveMachiningTask(payload).then(({ data }) => { saveMachiningTask(payload).then(({ data }) => {
@ -785,16 +825,73 @@ export default {
}) })
}, },
openReportDialog(row) { openReportDialog(row) {
const defaultNode = (row.nodeList || []).find(item => item.status !== '已完成') || {}
this.reportNodeOptions = (row.nodeList || []).filter(item => item.status !== '已完成')
const defaultNode = this.reportNodeOptions[0] || {}
const nodeCode = defaultNode.nodeCode || 'machiningProduction'
this.reportData = { this.reportData = {
orderNo: row.orderNo, orderNo: row.orderNo,
taskNo: row.orderNo, taskNo: row.orderNo,
nodeCode: defaultNode.nodeCode || 'machiningProduction',
reportQty: '',
nodeCode: nodeCode,
reportQty: this.isMachiningProductionNode(nodeCode) ? '' : 1,
remark: '' remark: ''
} }
this.clearInspectionImageList()
this.setUp.reportFlag = true this.setUp.reportFlag = true
}, },
handleReportNodeChange(nodeCode) {
if (this.isMachiningProductionNode(nodeCode)) {
this.reportData.reportQty = ''
} else {
this.reportData.reportQty = 1
}
if (!this.isMachiningInspectionNode(nodeCode)) {
this.clearInspectionImageList()
}
},
handleReportDialogClose() {
this.clearInspectionImageList()
},
triggerInspectionImagePicker() {
if (this.$refs.inspectionImageInput) {
this.$refs.inspectionImageInput.click()
}
},
handleInspectionImageSelect(event) {
const fileList = Array.from((event && event.target && event.target.files) || [])
if (!fileList.length) {
return
}
let invalidCount = 0
fileList.forEach(file => {
const fileType = String((file && file.type) || '').toLowerCase()
const fileName = String((file && file.name) || '').toLowerCase()
const isImage = fileType.indexOf('image/') === 0 || /\.(jpg|jpeg|png|gif|bmp|webp)$/.test(fileName)
if (!file || !isImage) {
invalidCount++
return
}
this.inspectionImageList.push({
uid: `${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
name: file.name || 'inspection-image',
raw: file
})
})
if (invalidCount > 0) {
this.$message.warning('仅支持上传图片文件')
}
if (event && event.target) {
event.target.value = ''
}
},
removeInspectionImage(index) {
this.inspectionImageList.splice(index, 1)
},
clearInspectionImageList() {
this.inspectionImageList = []
if (this.$refs.inspectionImageInput) {
this.$refs.inspectionImageInput.value = ''
}
},
openAssignDialog(row) { openAssignDialog(row) {
if (!row.orderNo) return this.$message.warning('请先保存任务单后再分配人员') if (!row.orderNo) return this.$message.warning('请先保存任务单后再分配人员')
this.currentAssignOrder = { orderNo: row.orderNo, orderType: 'MACHINING' } this.currentAssignOrder = { orderNo: row.orderNo, orderType: 'MACHINING' }
@ -835,10 +932,26 @@ export default {
}) })
}, },
submitNodeReport() { submitNodeReport() {
if (!this.reportData.reportQty || Number(this.reportData.reportQty) <= 0) return this.$message.warning('请输入有效报工数量')
if (!this.reportData.nodeCode) this.reportData.nodeCode = 'machiningProduction' if (!this.reportData.nodeCode) this.reportData.nodeCode = 'machiningProduction'
if (this.isMachiningProductionNode(this.reportData.nodeCode)) {
const qty = Number(this.reportData.reportQty)
if (!Number.isFinite(qty) || qty <= 0) return this.$message.warning('请输入有效报工数量')
this.submitMachiningProductionReport(qty)
return
}
if (this.isMachiningInspectionNode(this.reportData.nodeCode)) {
this.submitMachiningInspectionReport()
return
}
this.$message.warning('当前节点暂不支持报工')
},
submitMachiningProductionReport(reportQty) {
const payload = {
...this.reportData,
reportQty: reportQty
}
this.setUp.reportButton = true this.setUp.reportButton = true
reportMachiningTaskNode(this.reportData).then(({ data }) => {
reportMachiningTaskNode(payload).then(({ data }) => {
this.setUp.reportButton = false this.setUp.reportButton = false
if (data && data.code === 0) { if (data && data.code === 0) {
this.$message.success(data.msg || '报工成功') this.$message.success(data.msg || '报工成功')
@ -847,18 +960,54 @@ export default {
} else this.$message.error(data.msg || '报工失败') } else this.$message.error(data.msg || '报工失败')
}).catch(() => { }).catch(() => {
this.setUp.reportButton = false this.setUp.reportButton = false
this.simulateNodeReport(this.reportData.orderNo, this.reportData.nodeCode, this.reportData.reportQty)
this.simulateNodeReport(this.reportData.orderNo, this.reportData.nodeCode, reportQty)
this.setUp.reportFlag = false this.setUp.reportFlag = false
this.$message.success('后端未完成,已在前端演示节点报工') this.$message.success('后端未完成,已在前端演示节点报工')
}) })
}, },
submitMachiningInspectionReport() {
const uploadFileList = this.inspectionImageList.map(item => item.raw).filter(item => !!item)
if (!uploadFileList.length) {
return this.$message.warning('请先上传检验图片')
}
const formData = new FormData()
formData.append('orderNo', this.reportData.orderNo)
formData.append('orderType', 'MACHINING')
formData.append('nodeCode', this.reportData.nodeCode)
formData.append('reportQty', '1')
formData.append('remark', this.reportData.remark || '')
formData.append('reportNode', 'true')
uploadFileList.forEach(file => {
formData.append('file', file, file.name || 'inspection-image')
})
this.setUp.reportButton = true
reportWorkNodeWithMedia(formData).then(({ data }) => {
this.setUp.reportButton = false
if (data && data.code === 0) {
this.$message.success(data.msg || '检验报工成功')
this.setUp.reportFlag = false
this.clearInspectionImageList()
this.searchTable()
} else {
this.$message.error(data.msg || '检验报工失败')
}
}).catch(() => {
this.setUp.reportButton = false
this.simulateNodeReport(this.reportData.orderNo, this.reportData.nodeCode, 0)
this.setUp.reportFlag = false
this.clearInspectionImageList()
this.$message.success('后端未完成,已在前端演示检验报工')
})
},
simulateNodeReport(orderNo, nodeCode, qty) { simulateNodeReport(orderNo, nodeCode, qty) {
const row = this.dataList.find(item => item.orderNo === orderNo) const row = this.dataList.find(item => item.orderNo === orderNo)
if (!row) return if (!row) return
const node = row.nodeList.find(item => item.nodeCode === nodeCode) const node = row.nodeList.find(item => item.nodeCode === nodeCode)
if (!node) return if (!node) return
node.status = '已完成' node.status = '已完成'
row.reportQty = Number(row.reportQty || 0) + Number(qty || 0)
if (this.isMachiningProductionNode(nodeCode)) {
row.reportQty = Number(row.reportQty || 0) + Number(qty || 0)
}
row.status = '进行中' row.status = '进行中'
const nextNode = row.nodeList.find(item => item.status !== '已完成') const nextNode = row.nodeList.find(item => item.status !== '已完成')
row.currentNode = nextNode ? nextNode.nodeName : '全部完成' row.currentNode = nextNode ? nextNode.nodeName : '全部完成'
@ -1191,6 +1340,52 @@ export default {
padding: 8px; padding: 8px;
} }
.inspection-upload-wrap {
border: 1px dashed #dcdfe6;
border-radius: 4px;
padding: 10px;
}
.inspection-upload-tip {
margin-left: 8px;
color: #909399;
font-size: 12px;
}
.inspection-file-input {
display: none;
}
.inspection-file-list {
margin-top: 10px;
max-height: 150px;
overflow-y: auto;
}
.inspection-file-item {
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #f0f2f5;
padding: 4px 0;
}
.inspection-file-name {
flex: 1;
padding-right: 10px;
font-size: 12px;
color: #606266;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.inspection-upload-empty {
margin-top: 8px;
font-size: 12px;
color: #909399;
}
.media-dialog-body { .media-dialog-body {
min-height: 360px; min-height: 360px;
} }
@ -1259,7 +1454,39 @@ export default {
} }
.file-table { .file-table {
margin-top: 5px;
background-color: #fff;
border-radius: 4px;
}
.file-table >>> .cell {
line-height: 55px;
height: 55px;
}
.file-table >>> .el-table__header-wrapper th,
.file-table >>> .el-table__fixed-header-wrapper th {
background-color: #f5f7fa !important;
color: #333;
font-weight: 600;
border-color: #ebeef5;
padding: 8px 0;
}
.file-table >>> .el-table__header-wrapper .cell,
.file-table >>> .el-table__fixed-header-wrapper .cell{
padding: 0 10px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 13px !important;
line-height: 20px;
height: 20px;
}
.file-table >>> .el-table__body tr:hover > td {
background-color: #f5f7fa !important;
}
.file-table >>> .el-table__body tr.current-row > td {
background-color: #ecf5ff !important;
} }
.el-icon-check { .el-icon-check {

52
src/views/modules/longtron/production-plan-renovation-order.vue

@ -393,10 +393,9 @@ export default {
this.dataList = (data.page.list || []).map(this.normalizeRow) this.dataList = (data.page.list || []).map(this.normalizeRow)
this.totalPage = data.page.totalCount || 0 this.totalPage = data.page.totalCount || 0
this.syncSelectedOrder() this.syncSelectedOrder()
} else this.loadMockData()
}
}).catch(() => { }).catch(() => {
this.dataListLoading = false this.dataListLoading = false
this.loadMockData()
}) })
}, },
normalizeRow(row) { normalizeRow(row) {
@ -404,52 +403,9 @@ export default {
const done = list.filter(item => item.status === '已完成').length const done = list.filter(item => item.status === '已完成').length
const currentNode = (list.find(item => item.status !== '已完成') || {}).nodeName || '全部完成' const currentNode = (list.find(item => item.status !== '已完成') || {}).nodeName || '全部完成'
const assigneeSummary = list.filter(item => item.assigneeUserName).map(item => `${item.nodeName}:${item.assigneeUserName}`).join(';') const assigneeSummary = list.filter(item => item.assigneeUserName).map(item => `${item.nodeName}:${item.assigneeUserName}`).join(';')
return { ...row, autoAssignAllUsers: !!row.autoAssignAllUsers, nodeReportMode: row.nodeReportMode || 'PARALLEL', nodeList: list, nodeDoneCount: done, nodeTotalCount: list.length, currentNode: row.currentNode || currentNode, assigneeSummary: assigneeSummary || '-' }
},
loadMockData() {
this.dataList = [
{
orderNo: 'MOCK-RENOVATION-001',
projectNo: 'RNV-202604-001',
modelNo: 'LC-REN-630',
color: '钛金灰',
floorCount: 10,
autoAssignAllUsers: true,
nodeReportMode: 'PARALLEL',
specialRequirement: '井道尺寸受限,需优化导轨方案',
planDeliveryDate: '2026-04-28',
status: '进行中',
finishDate: '',
nodeList: [
{ nodeCode: 'stocking', nodeName: '仓库配料', status: '已完成' },
{ nodeCode: 'assy', nodeName: '组装', status: '进行中' },
{ nodeCode: 'inspect', nodeName: '检验', status: '未开始' },
{ nodeCode: 'pack', nodeName: '打包', status: '未开始' }
]
},
{
orderNo: 'MOCK-RENOVATION-002',
projectNo: 'RNV-202604-002',
modelNo: 'LC-REN-800',
color: '深空黑',
floorCount: 14,
autoAssignAllUsers: true,
nodeReportMode: 'PARALLEL',
specialRequirement: '兼容旧楼层召唤系统',
planDeliveryDate: '2026-05-06',
status: '已排产',
finishDate: '',
nodeList: [
{ nodeCode: 'stocking', nodeName: '仓库配料', status: '未开始' },
{ nodeCode: 'assy', nodeName: '组装', status: '未开始' },
{ nodeCode: 'inspect', nodeName: '检验', status: '未开始' },
{ nodeCode: 'pack', nodeName: '打包', status: '未开始' }
]
}
].map(this.normalizeRow)
this.totalPage = this.dataList.length
this.syncSelectedOrder()
return { ...row, autoAssignAllUsers: !!row.autoAssignAllUsers, nodeReportMode: row.nodeReportMode || 'SEQUENTIAL', nodeList: list, nodeDoneCount: done, nodeTotalCount: list.length, currentNode: row.currentNode || currentNode, assigneeSummary: assigneeSummary || '-' }
}, },
syncSelectedOrder() { syncSelectedOrder() {
if (!this.dataList.length) { if (!this.dataList.length) {
this.selectedOrder = {} this.selectedOrder = {}
@ -751,7 +707,7 @@ export default {
this.getDataList('Y') this.getDataList('Y')
}, },
openEditDialog(row) { openEditDialog(row) {
this.saveHeaderData = row ? { ...row, autoAssignAllUsers: !!row.autoAssignAllUsers, nodeReportMode: row.nodeReportMode || 'PARALLEL' } : { orderNo: '', projectNo: '', modelNo: '', color: '', floorCount: 1, specialRequirement: '', planDeliveryDate: '', status: '已排产', autoAssignAllUsers: true, nodeReportMode: 'PARALLEL', nodeList: [] }
this.saveHeaderData = row ? { ...row, autoAssignAllUsers: !!row.autoAssignAllUsers, nodeReportMode: row.nodeReportMode || 'SEQUENTIAL' } : { orderNo: '', projectNo: '', modelNo: '', color: '', floorCount: 1, specialRequirement: '', planDeliveryDate: '', status: '已排产', autoAssignAllUsers: true, nodeReportMode: 'SEQUENTIAL', nodeList: [] }
this.setUp.reviewFlag = true this.setUp.reviewFlag = true
}, },
isProjectNoDuplicate(projectNo, currentOrderNo) { isProjectNoDuplicate(projectNo, currentOrderNo) {

35
src/views/modules/longtron/production-work-report.vue

@ -5,7 +5,7 @@
<h2 class="page-title"> <h2 class="page-title">
<i class="el-icon-s-order"></i> 生产报工 <i class="el-icon-s-order"></i> 生产报工
</h2> </h2>
<p class="page-subtitle">家用电梯 / 线缆COP / 改造项目 / 机加工生产节点报工管理</p>
<p class="page-subtitle">家用电梯 / 线缆COP / 改造项目 / 机加工节点报工管理</p>
</div> </div>
<div class="header-right"> <div class="header-right">
<div class="stat-cards"> <div class="stat-cards">
@ -190,7 +190,7 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="24" v-if="isQtyRequired(reportData.orderType)">
<el-row :gutter="24" v-if="isQtyRequired(reportData.orderType, reportData.nodeCode, reportData.nodeName)">
<el-col :span="24"> <el-col :span="24">
<el-form-item label="报工数量" required> <el-form-item label="报工数量" required>
<el-input v-model="reportData.reportQty" style="width: 100%"></el-input> <el-input v-model="reportData.reportQty" style="width: 100%"></el-input>
@ -512,10 +512,11 @@ export default {
}, },
getModelFieldValue (item) { getModelFieldValue (item) {
if (!item) return '-' if (!item) return '-'
if (item.orderType === 'CABLE_COP') {
if (item.orderType === 'CABLE_COP' || item.orderType === 'MACHINING') {
const modelNo = item.modelNo || ''
const name = item.materialName || '' const name = item.materialName || ''
const spec = item.materialSpec || '' const spec = item.materialSpec || ''
if (name && spec) return `${name} / ${spec}`
if (modelNo && name && spec) return `${modelNo} / ${name} / ${spec}`
return name || spec || '-' return name || spec || '-'
} }
return item.modelNo || '-' return item.modelNo || '-'
@ -580,7 +581,11 @@ export default {
return return
} }
if (order.orderType === 'MACHINING') { if (order.orderType === 'MACHINING') {
this.openReportDialog(order, node, true)
if (this.requiresMediaUpload(order.orderType, node.nodeCode, node.nodeName)) {
this.openReportDialog(order, node, false)
} else {
this.openReportDialog(order, node, true)
}
return return
} }
if (this.requiresMediaUpload(order.orderType, node.nodeCode, node.nodeName)) { if (this.requiresMediaUpload(order.orderType, node.nodeCode, node.nodeName)) {
@ -589,8 +594,16 @@ export default {
} }
this.directReportNode(order, node) this.directReportNode(order, node)
}, },
isQtyRequired (orderType) {
return ['CABLE_COP', 'MACHINING'].includes(orderType)
isQtyRequired (orderType, nodeCode, nodeName) {
if (orderType === 'CABLE_COP') {
return true
}
if (orderType !== 'MACHINING') {
return false
}
const normalizedCode = String(nodeCode || '').trim()
const normalizedName = String(nodeName || '').replace(/\s+/g, '')
return normalizedCode === 'machiningProduction' || normalizedName === '机加工生产'
}, },
requiresMediaUpload (orderType, nodeCode, nodeName) { requiresMediaUpload (orderType, nodeCode, nodeName) {
if (!orderType) { if (!orderType) {
@ -604,6 +617,10 @@ export default {
RENOVATION: { RENOVATION: {
codeList: ['inspect', 'pack'], codeList: ['inspect', 'pack'],
nameList: ['检验', '打包'] nameList: ['检验', '打包']
},
MACHINING: {
codeList: ['machiningInspection'],
nameList: ['机加工检验', '检验']
} }
} }
const config = requiredMap[orderType] const config = requiredMap[orderType]
@ -680,7 +697,7 @@ export default {
this.$message.warning('请选择报工节点') this.$message.warning('请选择报工节点')
return return
} }
if (this.isQtyRequired(this.reportData.orderType)) {
if (this.isQtyRequired(this.reportData.orderType, this.reportData.nodeCode, this.reportData.nodeName)) {
const qty = Number(this.reportData.reportQty) const qty = Number(this.reportData.reportQty)
if (!Number.isFinite(qty) || qty <= 0) { if (!Number.isFinite(qty) || qty <= 0) {
this.$message.warning('请填写大于0的实际生产数量') this.$message.warning('请填写大于0的实际生产数量')
@ -807,7 +824,7 @@ export default {
}) })
}, },
buildNodeReportPayload () { buildNodeReportPayload () {
const reportQty = this.isQtyRequired(this.reportData.orderType) ? this.reportData.reportQty : 1
const reportQty = this.isQtyRequired(this.reportData.orderType, this.reportData.nodeCode, this.reportData.nodeName) ? this.reportData.reportQty : 1
return { return {
orderNo: this.reportData.orderNo, orderNo: this.reportData.orderNo,
nodeCode: this.reportData.nodeCode, nodeCode: this.reportData.nodeCode,

10
src/views/modules/longtron/screen-renovation-progress.vue

@ -96,6 +96,12 @@
<el-table-column prop="taskQty" label="计划数量" min-width="88" align="center"></el-table-column> <el-table-column prop="taskQty" label="计划数量" min-width="88" align="center"></el-table-column>
<el-table-column prop="reportQty" label="实际数量" min-width="88" align="center"></el-table-column> <el-table-column prop="reportQty" label="实际数量" min-width="88" align="center"></el-table-column>
<el-table-column prop="planFinishDate" label="计划完工日期" min-width="120" align="center"></el-table-column> <el-table-column prop="planFinishDate" label="计划完工日期" min-width="120" align="center"></el-table-column>
<el-table-column label="生产" min-width="65" align="center">
<template slot-scope="scope"><span :class="getNodeCellClass(scope.row, 'machiningProduction')"></span></template>
</el-table-column>
<el-table-column label="检验" min-width="65" align="center">
<template slot-scope="scope"><span :class="getNodeCellClass(scope.row, 'machiningInspection')"></span></template>
</el-table-column>
<el-table-column prop="status" label="任务状态" width="96" align="center"> <el-table-column prop="status" label="任务状态" width="96" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag class="board-tag" :class="getStatusTagClass(scope.row.status)" size="small">{{ scope.row.status }}</el-tag> <el-tag class="board-tag" :class="getStatusTagClass(scope.row.status)" size="small">{{ scope.row.status }}</el-tag>
@ -115,6 +121,7 @@ const STATUS_ALLOW_LIST = ['已排产', '进行中', '已完成']
const STATUS_EXCLUDE_FROM_LIST = ['已完成'] const STATUS_EXCLUDE_FROM_LIST = ['已完成']
const RENOVATION_NODE_TEMPLATE = ['stocking', 'assy', 'inspect', 'pack'] const RENOVATION_NODE_TEMPLATE = ['stocking', 'assy', 'inspect', 'pack']
const CABLE_COP_NODE_TEMPLATE = ['lineProduction', 'copProduction'] const CABLE_COP_NODE_TEMPLATE = ['lineProduction', 'copProduction']
const MACHINING_NODE_TEMPLATE = ['machiningProduction', 'machiningInspection']
const BOARD_PAGE_SIZE = 6 const BOARD_PAGE_SIZE = 6
export default { export default {
@ -302,7 +309,8 @@ export default {
status: item.status || '', status: item.status || '',
finishDate: item.finishDate || '', finishDate: item.finishDate || '',
taskQty: item.taskQty == null ? 0 : item.taskQty, taskQty: item.taskQty == null ? 0 : item.taskQty,
reportQty: item.reportQty == null ? 0 : item.reportQty
reportQty: item.reportQty == null ? 0 : item.reportQty,
nodeStatusMap: this.toNodeStatusMap(item.nodeList, MACHINING_NODE_TEMPLATE)
})) }))
}, },
toNodeStatusMap(nodeList, template) { toNodeStatusMap(nodeList, template) {

21
src/views/modules/sys/role-add-or-update.vue

@ -90,7 +90,8 @@ export default {
{ label: '改造项目-组装', value: 'LC_RENOVATION_ASSY' }, { label: '改造项目-组装', value: 'LC_RENOVATION_ASSY' },
{ label: '改造项目-检验', value: 'LC_RENOVATION_INSPECT' }, { label: '改造项目-检验', value: 'LC_RENOVATION_INSPECT' },
{ label: '改造项目-打包', value: 'LC_RENOVATION_PACK' }, { label: '改造项目-打包', value: 'LC_RENOVATION_PACK' },
{ label: '机加工生产-生产', value: 'LC_MACHINING_PRODUCTION' }
{ label: '机加工生产-生产', value: 'LC_MACHINING_PRODUCTION' },
{ label: '机加工生产-检验', value: 'LC_MACHINING_INSPECTION' }
], ],
dataForm: { dataForm: {
id: 0, id: 0,
@ -118,7 +119,8 @@ export default {
method: 'get', method: 'get',
params: this.$http.adornParams() params: this.$http.adornParams()
}).then(({data}) => { }).then(({data}) => {
this.menuList = treeDataTranslate(data, 'menuId')
const menuSource = this.deduplicateMenuListById(data)
this.menuList = treeDataTranslate(menuSource, 'menuId')
}).then(() => { }).then(() => {
this.visible = true this.visible = true
this.$nextTick(() => { this.$nextTick(() => {
@ -206,6 +208,21 @@ export default {
} }
}) })
}, },
deduplicateMenuListById(menuList) {
if (!Array.isArray(menuList) || menuList.length === 0) {
return []
}
const uniqueMap = new Map()
menuList.forEach(item => {
if (!item || !item.menuId) {
return
}
if (!uniqueMap.has(item.menuId)) {
uniqueMap.set(item.menuId, { ...item })
}
})
return Array.from(uniqueMap.values())
}
}, },
created() { created() {

18
src/views/modules/sys/role.vue

@ -17,6 +17,7 @@
<el-table <el-table
:data="dataList" :data="dataList"
border border
:height="tableHeight"
v-loading="dataListLoading" v-loading="dataListLoading"
@selection-change="selectionChangeHandle" @selection-change="selectionChangeHandle"
style="width: 100%;"> style="width: 100%;">
@ -68,7 +69,8 @@
:page-sizes="[20, 50, 100, 200,500]" :page-sizes="[20, 50, 100, 200,500]"
:page-size="pageSize" :page-size="pageSize"
:total="totalPage" :total="totalPage"
layout="total, sizes, prev, pager, next, jumper">
layout="total, sizes, prev, pager, next, jumper"
style="margin-top: 12px;">
</el-pagination> </el-pagination>
<!-- 弹窗, 新增 / 修改 --> <!-- 弹窗, 新增 / 修改 -->
<add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="getDataList"></add-or-update> <add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="getDataList"></add-or-update>
@ -153,8 +155,9 @@ import row from "element-ui/packages/row";
roleName: '' roleName: ''
}, },
dataList: [], dataList: [],
tableHeight: 600,
pageIndex: 1, pageIndex: 1,
pageSize: 20,
pageSize: 50,
totalPage: 0, totalPage: 0,
dataListLoading: false, dataListLoading: false,
dataListSelections: [], dataListSelections: [],
@ -191,14 +194,25 @@ import row from "element-ui/packages/row";
}, },
activated () { activated () {
this.favoriteIsOk() this.favoriteIsOk()
this.resetTableHeight()
this.getDataList() this.getDataList()
}, },
mounted () {
this.resetTableHeight()
window.addEventListener('resize', this.resetTableHeight)
},
beforeDestroy () {
window.removeEventListener('resize', this.resetTableHeight)
},
computed: { computed: {
adminUser() { adminUser() {
return this.$store.state.user.id === 1 return this.$store.state.user.id === 1
} }
}, },
methods: { methods: {
resetTableHeight () {
this.tableHeight = Math.max(window.innerHeight - 280, 600)
},
// //
favoriteIsOk() { favoriteIsOk() {
let userFavorite = { let userFavorite = {

Loading…
Cancel
Save