更新人事/采购/销售/精工/仓储/技术等模块,新增出库单/PDA采购入库页面,补充生产计划需求文档及多项SQL脚本

This commit is contained in:
Developer
2026-09-14 07:56:15 +08:00
parent 9fc3aae3e9
commit ffac9fcc61
40 changed files with 6762 additions and 181 deletions

View File

@@ -656,6 +656,7 @@ import {
tree,
getTablePeople,
getTablePeopleForName,
checkAttendanceNumber,
addDepartmentName,
delList,
editList,
@@ -1151,17 +1152,39 @@ export default {
submitAddPeople() {
this.addPeople_disable = true
this.btnLoading = true
addPeople(this.id, this.people_form.Sex, this.people_form.Education, this.people_form.Address, this.people_form.Nation, this.people_form.Post, this.people_form.AccountNumber, this.people_form.Password, this.people_form.Name, this.people_form.IDcard, this.people_form.TimeOfEntry, this.people_form.Birthday, this.people_form.ContactInformation, this.people_form.TeamValue).then(response => {
this.btnLoading = false
if (response.data[0].result === '1') {
this.people_DFV = false
this.i = 0
this.handleNodeClick()
this.$message.success('添加成功')
} else {
this.$message.error('添加失败')
// 修改人:Ld 修改时间:2026-09-09 15:30:17; 先查考勤编号是否重复,重复时拦截新增避免接口返回添加成功
checkAttendanceNumber(this.people_form.AccountNumber).then(response => {
if (response.data[0].是否重复 === 1 || response.data[0].是否重复 === '1') {
this.btnLoading = false
this.addPeople_disable = false
this.$message.error('考勤编号已有,现在已到' + response.data[0].最大考勤编号)
} else {
addPeople(this.id, this.people_form.Sex, this.people_form.Education, this.people_form.Address, this.people_form.Nation, this.people_form.Post, this.people_form.AccountNumber, this.people_form.Password, this.people_form.Name, this.people_form.IDcard, this.people_form.TimeOfEntry, this.people_form.Birthday, this.people_form.ContactInformation, this.people_form.TeamValue).then(response => {
this.btnLoading = false
if (response.data[0].result === '1') {
this.people_DFV = false
this.i = 0
this.handleNodeClick()
this.$message.success('添加成功')
} else {
// 修改人:Ld 修改时间:2026-09-09 15:19:32; 考勤编号重复时显示测试库返回的同前缀最大编号
if (response.data[0].失败原因 === '考勤编号重复' && response.data[0].最大考勤编号) {
this.$message.error('考勤编号已有,现在已到' + response.data[0].最大考勤编号)
} else {
this.$message.error('添加失败')
}
this.addPeople_disable = false
}
}).catch(() => {
this.btnLoading = false
this.addPeople_disable = false
this.$message.error('添加失败')
})
}
}).catch(() => {
this.btnLoading = false
this.addPeople_disable = false
this.$message.error('考勤编号校验失败')
})
},
handleEditPeople(row) {
@@ -1320,4 +1343,3 @@ export default {
<style scoped>
</style>

View File

@@ -62,7 +62,6 @@
placeholder="订单备注"
@keyup.enter.native="pageCurrent=1;searchLeftTable()"/>
<el-button type="success" size="mini" style="margin-left: 100px" @click="exportExcel()">导出</el-button>
<el-button type="distribution" icon="el-icon-plus" size="mini" @click="addArrivalNotice()">生成入库单</el-button>
</div>
<el-row style="display: flex">
<el-col style="margin-left: 7px;width: 571px">
@@ -145,13 +144,22 @@
{{ getApproverName(scope.row.审批人) }}
</template>
</el-table-column>
<el-table-column width="120px" label="操作" align="center" show-overflow-tooltip fixed="right">
<!-- 修改人:Ld 修改时间:2026-09-03 14:37:23; 生成入库单按钮加入后适当加宽左侧合同操作列。 -->
<el-table-column width="150px" label="操作" align="center" show-overflow-tooltip fixed="right">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-printer"
@click="exportTable(scope.row)"/>
<el-tooltip :open-delay="700" effect="dark" content="生成入库单" placement="top">
<!-- 修改人:Ld 修改时间:2026-09-03 14:37:23; 将生成入库单入口移至左侧合同列表当前合同操作列。 -->
<el-button
size="mini"
type="text"
icon="el-icon-plus"
@click.stop="addArrivalNotice(scope.row)"/>
</el-tooltip>
<el-tooltip :open-delay="700" effect="dark" content="删除合同" placement="top">
<el-button
:disabled="Number(scope.row.是否提交) !== 0 && Number(scope.row.审批情况流水号)===1"
@@ -562,21 +570,17 @@
<el-table-column label="最近一次采购单价" align="center" prop="最近单价"/>
</el-table>
</el-dialog>
<el-dialog v-el-drag-dialog title="生成入库单" :visible.sync="dialogFormVisible4" center width="1000px">
<el-dialog v-el-drag-dialog :visible.sync="dialogFormVisible4" center title="生成入库单" width="1000px">
<el-form label-position="left" label-width="100px" class="demo-ruleForm" style="margin: auto">
<el-row style="display: flex; align-items: center;">
<el-col>
<el-select v-model="arrivalSupplierName" filterable clearable placeholder="请选择供应商" size="small" style="width: 200px" @change="getArrivalContract()">
<el-option v-for="item in suppliers" :key="item.value" :label="item.label" :value="item.value"/>
</el-select>
<!-- 修改人:Ld 修改时间:2026-09-03 14:37:23; 弹窗改为展示当前合同信息,不再二次选择供应商和合同。 -->
<el-row class="arrival-current-contract">
<el-col :span="6">
<span>采购合同号:</span>
<strong>{{ arrivalContractLabel || '-' }}</strong>
</el-col>
<el-col>
<el-select v-model="arrivalContractNo" filterable clearable placeholder="请选择合同号" size="small" style="width: 200px" @change="onArrivalContractChange">
<el-option v-for="item in arrivalContract" :key="item.value" :label="item.label" :value="item.value"/>
</el-select>
</el-col>
<el-col>
<el-button icon="el-icon-search" type="primary" plain size="small" @click="searchArrivalDetail()">查询</el-button>
<el-col :span="6">
<span>供应商:</span>
<strong>{{ arrivalSupplierLabel || '-' }}</strong>
</el-col>
<el-col v-if="入库单号" style="margin-left: 20px;">
<span style="font-size: 14px; color: #606266;">入库单号:</span>
@@ -586,10 +590,19 @@
<el-row>
<el-col :span="24">
<div style="max-height: 400px; overflow: auto;">
<el-table :data="arrivalTableData" border stripe size="small" style="width: 100%;">
<el-table
ref="arrivalTable"
:data="arrivalTableData"
border
stripe
size="small"
style="width: 100%;"
@selection-change="handleArrivalSelectionChange">
<!-- 修改人:Ld 修改时间:2026-09-03 14:37:23; 增加明细勾选列,仅提交用户选择且数量大于0的物料。 -->
<el-table-column type="selection" width="45" align="center"/>
<el-table-column label="合同号" align="center" show-overflow-tooltip width="180">
<template slot-scope="scope">
{{ scope.row.采购合同编号 }}
{{ scope.row.采购合同编号 || arrivalContractLabel }}
</template>
</el-table-column>
<el-table-column label="采购件" align="center" show-overflow-tooltip width="150">
@@ -616,11 +629,12 @@
<template slot-scope="scope">
<el-input-number
v-model="scope.row.到货数量"
:max="scope.row.采购数 - (scope.row.已到数 || 0)"
:max="getCanArrivalCount(scope.row)"
:min="0"
size="small"
style="width: 120px"
controls-position="right"/>
controls-position="right"
@change="onArrivalCountChange(scope.row)"/>
</template>
</el-table-column>
<el-table-column label="是否需要质检" align="center" width="120">
@@ -646,9 +660,11 @@
<el-col :span="24">
<el-divider content-position="left">到货汇总</el-divider>
<div style="font-size: 12px; color: #606266; background: #f5f7fa; padding: 10px; border-radius: 4px;">
<!-- 修改人:Ld 修改时间:2026-09-03 15:10:12; 汇总区增加按勾选明细数量变化的数量合计。 -->
<span>本次到货物料数:<span style="color: #409EFF; font-weight: bold;">{{ arrivalCount }}</span> 个,</span>
<span>其中需质检:<span style="color: #E6A23C; font-weight: bold;">{{ qualityCheckCount }}</span> 个 → 推送质检部,</span>
<span>免检直接入库:<span style="color: #67C23A; font-weight: bold;">{{ noQualityCheckCount }}</span> 个 → 推送仓库</span>
<span>本次数量合计:<span style="color: #409EFF; font-weight: bold;">{{ arrivalTotalQuantity }}</span>,</span>
<span>其中需质检:<span style="color: #E6A23C; font-weight: bold;">{{ qualityCheckCount }}</span> 个 / <span style="color: #E6A23C; font-weight: bold;">{{ qualityCheckTotalQuantity }}</span> → 推送质检部,</span>
<span>免检直接入库:<span style="color: #67C23A; font-weight: bold;">{{ noQualityCheckCount }}</span> 个 / <span style="color: #67C23A; font-weight: bold;">{{ noQualityCheckTotalQuantity }}</span> → 推送仓库</span>
</div>
</el-col>
</el-row>
@@ -658,6 +674,30 @@
<el-button type="primary" size="small" @click="submitArrivalNotice()">确 定</el-button>
</div>
</el-dialog>
<el-dialog v-el-drag-dialog :visible.sync="arrivalLabelVisible" center title="入库单标签" width="420px">
<!-- 修改人:Ld 修改时间:2026-09-03 14:37:23; 前端先生成入库单标签预览,后端补充标签ID后可替换二维码内容。 -->
<div id="purchaseInboundLabel" class="purchase-inbound-label">
<div class="label-title">采购入库标签</div>
<div class="label-body">
<div class="label-info">
<div><span>采购合同号</span><strong>{{ arrivalLabelInfo.采购合同号 }}</strong></div>
<div><span>供应商</span><strong>{{ arrivalLabelInfo.供应商 }}</strong></div>
<div><span>批次号</span><strong>{{ arrivalLabelInfo.批次号 }}</strong></div>
<div><span>入库单号</span><strong>{{ arrivalLabelInfo.入库单号 }}</strong></div>
</div>
<img v-if="arrivalLabelInfo.二维码" :src="arrivalLabelInfo.二维码" class="label-qrcode">
</div>
<div class="label-detail">
<div v-for="(item, index) in arrivalLabelInfo.明细" :key="index">
{{ index + 1 }}. {{ item.物料名称 }} / {{ item.图号 }} / {{ item.数量 }}
</div>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button size="small" @click="arrivalLabelVisible = false">关闭</el-button>
<el-button type="primary" size="small" icon="el-icon-printer" @click="printArrivalLabel()">打印标签</el-button>
</div>
</el-dialog>
</div>
</template>
@@ -666,6 +706,7 @@ import { mapGetters } from 'vuex'
import $ from 'jquery'
import request, { MESDownloadFile, MESUploadFileNew, MESDownloadFileNew, MESDeleteFileNew, MESUploadFileNew_BasePath, url } from '@/utils/request'
import axios from 'axios'
import QRCode from 'qrcode'
export default {
data() {
@@ -744,6 +785,17 @@ export default {
arrivalContractNo: '',
arrivalContract: [],
arrivalContractLabel: '',
arrivalSupplierLabel: '',
arrivalSelectedRows: [],
arrivalLabelVisible: false,
arrivalLabelInfo: {
采购合同号: '',
供应商: '',
批次号: '',
入库单号: '',
二维码: '',
明细: []
},
arrivalNoticeLabel: '',
arrivalTableData: [],
入库单号: ''
@@ -755,16 +807,27 @@ export default {
'token'
]),
hasArrivalData() {
return this.arrivalTableData.some(item => item.到货数量 > 0)
// 修改人:Ld 修改时间:2026-09-03 14:37:23; 到货汇总按勾选行统计,和提交口径保持一致。
return this.arrivalSelectedRows.some(item => item.到货数量 > 0)
},
arrivalCount() {
return this.arrivalTableData.filter(item => item.到货数量 > 0).length
return this.arrivalSelectedRows.filter(item => item.到货数量 > 0).length
},
qualityCheckCount() {
return this.arrivalTableData.filter(item => item.到货数量 > 0 && item.需要质检).length
return this.arrivalSelectedRows.filter(item => item.到货数量 > 0 && item.需要质检).length
},
noQualityCheckCount() {
return this.arrivalTableData.filter(item => item.到货数量 > 0 && !item.需要质检).length
return this.arrivalSelectedRows.filter(item => item.到货数量 > 0 && !item.需要质检).length
},
// 修改人:Ld 修改时间:2026-09-03 15:10:12; 按勾选行实时合计本次到货数量,避免只看物料行数。
arrivalTotalQuantity() {
return this.sumArrivalQuantity(this.arrivalSelectedRows.filter(item => item.到货数量 > 0))
},
qualityCheckTotalQuantity() {
return this.sumArrivalQuantity(this.arrivalSelectedRows.filter(item => item.到货数量 > 0 && item.需要质检))
},
noQualityCheckTotalQuantity() {
return this.sumArrivalQuantity(this.arrivalSelectedRows.filter(item => item.到货数量 > 0 && !item.需要质检))
}
},
updated() {
@@ -1128,14 +1191,35 @@ export default {
}
}).then(() => {
const htmlNode = $('#WGBLD').html()
const body = $('body')
body.children().hide()
const printNode = $(htmlNode)
body.append(printNode)
window.print()
body.children().not('script').show()
body.children().not('#app').hide()
printNode.remove()
// 修改人:Ld 修改时间:2026-08-19 09:16:26; 使用隐藏iframe承载采购合同打印内容
const printTitle = (row.采购合同号 || this.orderNumber || '采购合同').replace(/[\\/:*?"<>|]/g, '_')
// 修改人:Ld 修改时间:2026-08-19 09:21:49; PDF默认文件名取主页面临时title,打印显示title取原页面title
const oldTitle = document.title
const frameTitleHtml = oldTitle.replace(/[&<>"']/g, function(value) {
return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[value]
})
const printFrame = document.createElement('iframe')
printFrame.style.position = 'fixed'
printFrame.style.right = '0'
printFrame.style.bottom = '0'
printFrame.style.width = '0'
printFrame.style.height = '0'
printFrame.style.border = '0'
document.body.appendChild(printFrame)
const printWindow = printFrame.contentWindow
const printDocument = printWindow.document
printDocument.open()
printDocument.write('<!doctype html><html><head><meta charset="utf-8"><title>' + frameTitleHtml + '</title></head><body></body></html>')
printDocument.close()
printDocument.body.innerHTML = htmlNode
try {
document.title = printTitle
printWindow.focus()
printWindow.print()
} finally {
document.title = oldTitle
document.body.removeChild(printFrame)
}
})
},
getSuppliers() {
@@ -1440,22 +1524,43 @@ export default {
}
return approverId
},
addArrivalNotice() {
this.arrivalSupplierName = ''
this.arrivalContractNo = ''
this.arrivalContractLabel = ''
this.arrivalNoticeLabel = ''
this.arrivalContract = []
// 修改人:Ld 修改时间:2026-09-03 14:37:23; 从左侧合同列表打开生成入库单弹窗,自动带入当前合同上下文。
addArrivalNotice(row) {
if (!row || !row.采购合同流水号) {
this.$message.warning('请从左侧合同列表选择合同生成入库单')
return
}
this.arrivalSupplierName = row.供应商流水号 || this.getSupplierValueByName(row.供应商)
this.arrivalSupplierLabel = row.供应商 || ''
this.arrivalContractNo = row.采购合同流水号
this.arrivalContractLabel = row.采购合同号 || row.采购合同编号 || ''
this.arrivalNoticeLabel = this.arrivalContractLabel
this.arrivalContract = [{
label: this.arrivalContractLabel,
value: this.arrivalContractNo
}]
this.arrivalSelectedRows = []
this.arrivalLabelVisible = false
this.arrivalLabelInfo = {
采购合同号: '',
供应商: '',
批次号: '',
入库单号: '',
二维码: '',
明细: []
}
this.arrivalTableData = []
this.入库单号 = ''
this.dialogFormVisible4 = true
this.searchArrivalDetail()
},
getArrivalContract() {
if (!this.arrivalSupplierName) {
this.arrivalContract = []
return
}
let check = this.arrivalSupplierName ? 1 : 0
// 修改人:Ld 修改时间:2026-09-03 14:37:23; 修正变量声明以满足项目ESLint规则。
const check = this.arrivalSupplierName ? 1 : 0
this.arrivalContract = []
this.arrivalContractNo = ''
var param = []
@@ -1478,11 +1583,11 @@ export default {
},
searchArrivalDetail() {
if (!this.arrivalSupplierName) {
this.$message.warning('请先选择供应商')
this.$message.warning('当前合同缺少供应商流水号')
return
}
if (!this.arrivalContractNo) {
this.$message.warning('请先选择合同号')
this.$message.warning('当前合同缺少合同流水号')
return
}
var param = []
@@ -1492,7 +1597,7 @@ export default {
this.ExecDatabase(Data).then(response => {
this.arrivalTableData = response.data.map(item => ({
...item,
到货数量: 0,
到货数量: this.getCanArrivalCount(item),
需要质检: false
}))
if (this.arrivalTableData.length === 0) {
@@ -1502,13 +1607,60 @@ export default {
if (response.data.length > 0 && response.data[0].入库单号) {
this.入库单号 = response.data[0].入库单号
}
this.$nextTick(() => {
if (this.$refs.arrivalTable) {
this.arrivalTableData.forEach(item => {
if (this.getCanArrivalCount(item) > 0) {
this.$refs.arrivalTable.toggleRowSelection(item, true)
}
})
}
})
})
},
// 修改人:Ld 修改时间:2026-09-03 14:37:23; 合同列表未返回供应商流水号时,按供应商名称从已加载选项中兜底匹配。
getSupplierValueByName(name) {
if (!name) {
return ''
}
const selected = this.suppliers.find(item => item.label === name)
return selected ? selected.value : ''
},
// 修改人:Ld 修改时间:2026-09-03 14:37:23; 记录本次用户勾选的入库明细。
handleArrivalSelectionChange(val) {
this.arrivalSelectedRows = val
},
// 修改人:Ld 修改时间:2026-09-03 14:37:23; 统一计算可入库数量,避免前端出现负数或超入。
getCanArrivalCount(row) {
var purchaseCount = Number(row.采购数 || 0)
var arrivedCount = Number(row.已到数 || 0)
var canArrivalCount = purchaseCount - arrivedCount
return canArrivalCount > 0 ? canArrivalCount : 0
},
// 修改人:Ld 修改时间:2026-09-03 14:37:23; 数量清零时同步取消质检标志。
onArrivalCountChange(row) {
if (Number(row.到货数量) === 0) {
row.需要质检 = false
}
},
// 修改人:Ld 修改时间:2026-09-03 15:10:12; 汇总勾选明细的本次到货数量。
sumArrivalQuantity(list) {
var total = list.reduce(function(sum, item) {
var value = Number(item.到货数量 || 0)
return sum + (isNaN(value) ? 0 : value)
}, 0)
return Number(total.toFixed(4))
},
submitArrivalNotice() {
const arrivalData = this.arrivalTableData.filter(item => item.到货数量 > 0)
const arrivalData = this.arrivalSelectedRows.filter(item => Number(item.到货数量) > 0)
if (arrivalData.length === 0) {
this.$message.warning('请至少填写一个物料的到货数量!')
this.$message.warning('请至少勾选一个物料并填写到货数量!')
return
}
const invalidArrival = arrivalData.some(item => Number(item.到货数量) > this.getCanArrivalCount(item))
if (invalidArrival) {
this.$message.warning('存在超出可入库数量的物料,请检查')
return
}
const toQualityCheck = arrivalData.filter(item => item.需要质检 === true)
@@ -1538,6 +1690,7 @@ export default {
type: 'success',
duration: 3000
})
this.createArrivalLabel(response.data[0], arrivalData)
this.searchLeftTable()
this.dialogFormVisible4 = false
} else {
@@ -1551,6 +1704,57 @@ export default {
this.dialogFormVisible4 = false
this.$message.warning('已取消')
},
// 修改人:Ld 修改时间:2026-09-03 14:37:23; 生成前端入库标签二维码,暂用现有入库单号和合同号承载扫码内容。
createArrivalLabel(result, arrivalData) {
var inboundNo = result.入库单号 || this.入库单号 || ''
var batchNo = result.批次号 || result.批次编号 || inboundNo
// 修改人:Ld 修改时间:2026-09-03 14:56:40; 后端返回标签二维码内容后优先使用后端值,兼容未部署后端时的前端占位内容。
var qrContent = result.二维码内容 || JSON.stringify({
type: 'purchaseInbound',
标签ID: result.标签ID || '',
标签编号: result.标签编号 || '',
入库单号: inboundNo,
采购合同号: this.arrivalContractLabel,
批次号: batchNo
})
QRCode.toDataURL(qrContent, { margin: 1, width: 150 }).then(url => {
this.arrivalLabelInfo = {
采购合同号: this.arrivalContractLabel,
供应商: this.arrivalSupplierLabel,
批次号: batchNo,
入库单号: inboundNo,
二维码: url,
明细: arrivalData.map(item => ({
物料名称: item.物料名称 || item.采购件 || '',
图号: item.图号或型号 || item.图号 || '',
数量: item.到货数量
}))
}
this.arrivalLabelVisible = true
}).catch(() => {
this.$message.error('二维码生成失败')
})
},
// 修改人:Ld 修改时间:2026-09-03 14:37:23; 使用隐藏iframe打印入库单标签,避免影响当前页面显示状态。
printArrivalLabel() {
const htmlNode = $('#purchaseInboundLabel').html()
const printFrame = document.createElement('iframe')
printFrame.style.position = 'fixed'
printFrame.style.right = '0'
printFrame.style.bottom = '0'
printFrame.style.width = '0'
printFrame.style.height = '0'
printFrame.style.border = '0'
document.body.appendChild(printFrame)
const printWindow = printFrame.contentWindow
const printDocument = printWindow.document
printDocument.open()
printDocument.write('<!doctype html><html><head><meta charset="utf-8"><title>入库单标签</title><style>.purchase-inbound-label{width:360px;padding:12px;font-family:Arial,\"Microsoft YaHei\",sans-serif;color:#303133;border:1px solid #303133}.label-title{text-align:center;font-size:18px;font-weight:bold;margin-bottom:10px}.label-body{display:flex;align-items:center;justify-content:space-between}.label-info{font-size:12px;line-height:1.8}.label-info span{display:inline-block;width:70px;color:#606266}.label-info strong{font-size:13px;color:#303133}.label-qrcode{width:120px;height:120px}.label-detail{margin-top:8px;padding-top:8px;border-top:1px solid #dcdfe6;font-size:11px;line-height:1.6}</style></head><body><div class="purchase-inbound-label">' + htmlNode + '</div></body></html>')
printDocument.close()
printWindow.focus()
printWindow.print()
document.body.removeChild(printFrame)
},
showHistoryPrice(row) {
var param = []
param[0] = ['采购合同流水号', row.采购合同流水号]
@@ -1648,4 +1852,82 @@ a {
display: inline-block;
color: #999;
}
/* 修改人:Ld 修改时间:2026-09-03 14:37:23; 当前合同入库弹窗和标签预览样式。 */
.arrival-current-contract {
display: flex;
align-items: center;
margin-bottom: 10px;
padding: 10px;
border: 1px solid #dcdfe6;
border-radius: 4px;
background: #f5f7fa;
font-size: 14px;
}
.arrival-current-contract span {
color: #606266;
}
.arrival-current-contract strong {
color: #303133;
}
.purchase-inbound-label {
width: 360px;
margin: 0 auto;
padding: 12px;
border: 1px solid #303133;
color: #303133;
font-family: Arial, "Microsoft YaHei", sans-serif;
}
.label-title {
margin-bottom: 10px;
text-align: center;
font-size: 18px;
font-weight: bold;
}
.label-body {
display: flex;
align-items: center;
justify-content: space-between;
}
.label-info {
max-width: 220px;
font-size: 12px;
line-height: 1.8;
}
.label-info span {
display: inline-block;
width: 70px;
color: #606266;
}
.label-info strong {
display: inline-block;
max-width: 140px;
overflow: hidden;
color: #303133;
font-size: 13px;
text-overflow: ellipsis;
vertical-align: top;
white-space: nowrap;
}
.label-qrcode {
width: 120px;
height: 120px;
}
.label-detail {
margin-top: 8px;
padding-top: 8px;
border-top: 1px solid #dcdfe6;
font-size: 11px;
line-height: 1.6;
}
</style>

View File

@@ -52,9 +52,13 @@
@click="exportExcel">导出</el-button>
</div>
<!-- 修改人:Ld 修改时间:2026-09-11 14:05:14; 开启销售绩效表格底部自定义汇总行。 -->
<el-table
ref="performanceTable"
v-loading="loading"
:data="pageTableData"
:summary-method="getSummaries"
show-summary
border
stripe
size="small"
@@ -89,13 +93,14 @@
<el-table-column width="100px" label="销售员" align="center" prop="销售员" show-overflow-tooltip />
<el-table-column width="160px" label="合同编号" align="center" prop="合同编号" show-overflow-tooltip />
<el-table-column width="220px" label="客户名称" align="center" prop="客户名称" show-overflow-tooltip />
<el-table-column width="120px" label="合同金额" align="right">
<!-- 修改人:Ld 修改时间:2026-09-11 14:05:14; 指定金额列字段用于表格底部汇总。 -->
<el-table-column width="120px" label="合同金额" align="right" prop="合同金额">
<template slot-scope="scope">{{ formatMoney(scope.row.合同金额) }}</template>
</el-table-column>
<el-table-column width="120px" label="累计回款金额" align="right">
<el-table-column width="120px" label="累计回款金额" align="right" prop="累计回款金额">
<template slot-scope="scope">{{ formatMoney(scope.row.累计回款金额) }}</template>
</el-table-column>
<el-table-column width="120px" label="本月回款金额" align="right">
<el-table-column width="120px" label="本月回款金额" align="right" prop="本月回款金额">
<template slot-scope="scope">{{ formatMoney(scope.row.本月回款金额) }}</template>
</el-table-column>
<el-table-column width="100px" label="回款比例" align="right">
@@ -105,7 +110,7 @@
<el-table-column width="100px" label="提成比例" align="right">
<template slot-scope="scope">{{ formatPercent(scope.row.提成比例) }}</template>
</el-table-column>
<el-table-column width="130px" label="本月绩效金额" align="right">
<el-table-column width="130px" label="本月绩效金额" align="right" prop="本月绩效金额">
<template slot-scope="scope">{{ formatMoney(scope.row.本月绩效金额) }}</template>
</el-table-column>
</el-table>
@@ -179,6 +184,7 @@ export default {
this.ExecDatabase(Data).then(response => {
this.tableData = response.data || []
this.loading = false
this.refreshTableLayout()
}).catch(() => {
this.loading = false
this.$message.error('销售绩效查询失败')
@@ -216,14 +222,45 @@ export default {
handleSizeChanges(val) {
this.pageSize = val
this.pageCurrent = 1
this.refreshTableLayout()
},
handleCurrentChanges(val) {
this.pageCurrent = val
this.refreshTableLayout()
},
formatMoney(value) {
const num = Number(value || 0)
return num.toFixed(2)
},
getSummaries(param) {
// 修改人:Ld 修改时间:2026-09-11 14:05:14; 表格底部仅汇总合同金额、累计回款金额、本月回款金额、本月绩效金额。
const summaryFields = ['合同金额', '累计回款金额', '本月回款金额', '本月绩效金额']
const sums = []
param.columns.forEach((column, index) => {
if (column.type === 'index') {
sums[index] = '合计'
return
}
if (summaryFields.indexOf(column.property) === -1) {
sums[index] = ''
return
}
const total = this.tableData.reduce((sum, row) => {
const value = Number(row[column.property])
return sum + (isNaN(value) ? 0 : value)
}, 0)
sums[index] = this.formatMoney(total)
})
return sums
},
refreshTableLayout() {
// 修改人:Ld 修改时间:2026-09-11 14:14:13; 数据加载和分页切换后刷新表格布局,保证汇总行默认显示。
this.$nextTick(() => {
if (this.$refs.performanceTable) {
this.$refs.performanceTable.doLayout()
}
})
},
formatPercent(value) {
const num = Number(value || 0)
return num.toFixed(2) + '%'

View File

@@ -3,6 +3,14 @@
<div class="app-container production-completion-audit">
<el-card>
<div class="search-bar">
<!-- 生产审核添加订单号查询 修改人:Ld 修改时间:2026-08-11 10:08:01; -->
<el-input
v-model="searchForm.订单号"
style="width: 150px"
placeholder="订单号"
size="small"
clearable
@keyup.enter.native="resetSearch"/>
<el-input
v-model="searchForm.操作者"
style="width: 140px"
@@ -107,14 +115,16 @@
<el-table-column label="操作" align="center" width="170" fixed="right">
<template slot-scope="scope">
<el-button type="text" size="mini" icon="el-icon-view" @click="openDetail(scope.row)">查看</el-button>
<!-- 修改人:Ld 修改时间:2026-08-20 13:20:11; 系统管理员可对已审核记录再次审核 -->
<el-button
:disabled="scope.row.审核状态 !== '待审核'"
:disabled="!canAuditAgain(scope.row)"
type="text"
size="mini"
icon="el-icon-check"
@click="approveRow(scope.row)">通过</el-button>
<!-- 修改人:Ld 修改时间:2026-08-20 13:20:11; 系统管理员可对已审核记录再次修改后审核 -->
<el-button
:disabled="scope.row.审核状态 !== '待审核'"
:disabled="!canAuditAgain(scope.row)"
type="text"
size="mini"
icon="el-icon-edit"
@@ -229,7 +239,8 @@ export default {
editForm: {
审核类型: '',
完成数量: 1,
计价方式: '计件',
// 修改人:Ld 修改时间:2026-08-20 13:20:11; 默认计价方式改为计时
计价方式: '计时',
加工开始时间: '',
加工完成时间: '',
整修开始时间: '',
@@ -237,6 +248,8 @@ export default {
整修方案: ''
},
searchForm: {
// 生产审核添加订单号查询 修改人:Ld 修改时间:2026-08-11 10:08:01;
订单号: '',
操作者: '',
审核类型: '',
审核状态: '待审核'
@@ -262,6 +275,14 @@ export default {
this.getPeople()
},
methods: {
// 修改人:Ld 修改时间:2026-08-20 13:20:11; 判断当前角色是否为系统管理员
isSystemAdmin() {
return String(this.token) === '2'
},
// 修改人:Ld 修改时间:2026-08-20 13:20:11; 仅待审核或系统管理员再次审核的记录允许操作
canAuditAgain(row) {
return row && (row.审核状态 === '待审核' || (row.审核状态 === '已审核' && this.isSystemAdmin()))
},
// 生产完成审核查询 修改人:Ld 修改时间:2026-07-02 13:57:18;
getPeople() {
var param = []
@@ -296,10 +317,19 @@ export default {
param[6] = ['时间_check', dateRangeCheck]
param[7] = ['开始时间', dateRangeCheck ? this.dateRange[0] : '']
param[8] = ['结束时间', dateRangeCheck ? this.dateRange[1] : '']
// 生产审核添加订单号查询 修改人:Ld 修改时间:2026-08-11 10:08:01;
param[9] = ['订单号_check', this.searchForm.订单号 ? 1 : 0]
param[10] = ['订单号', this.searchForm.订单号]
this.loading = true
var Data = this.CreateData('11', '机加工MES_加工完成整修审核_查询数据', param, this.pageSize, this.pageCurrent)
this.ExecDatabase(Data).then(response => {
this.tableData = response.data.rows || []
this.tableData = (response.data.rows || []).map(row => {
// 修改人:Ld 修改时间:2026-08-20 13:20:11; 加工完成记录默认按计时显示和提交
if (row && row.审核类型 === '加工完成' && !row.计价方式) {
row.计价方式 = '计时'
}
return row
})
this.total = Number(response.data.total || 0)
}).catch(() => {
this.tableData = []
@@ -315,6 +345,8 @@ export default {
},
resetForm() {
this.searchForm = {
// 生产审核添加订单号查询 修改人:Ld 修改时间:2026-08-11 10:08:01;
订单号: '',
操作者: '',
审核类型: '',
审核状态: '待审核'
@@ -393,7 +425,8 @@ export default {
审核类型: row.审核类型,
// 保留 0 完成数量,避免审核修改弹窗将 0 自动改成 1;修改人:Ld 修改时间:2026-07-15 10:06:11;
完成数量: row.完成数量 === null || row.完成数量 === undefined || row.完成数量 === '' ? 1 : Number(row.完成数量),
计价方式: row.计价方式 || '计件',
// 修改人:Ld 修改时间:2026-08-20 13:20:11; 计价方式默认选项改为计时
计价方式: row.计价方式 || '计时',
加工开始时间: row.开始时间 || '',
加工完成时间: row.结束时间 || '',
整修开始时间: row.开始时间 || '',
@@ -443,6 +476,8 @@ export default {
param[1] = ['审核状态', state]
param[2] = ['审核人', this.id]
param[3] = ['审核意见', opinion]
// 修改人:Ld 修改时间:2026-08-20 13:20:11; 传入角色编号供后端区分系统管理员重审
param[4] = ['角色编号', this.token]
if (editData && editData.finishQuantity !== undefined) {
// 仅修改数量通过时传审核完成数量,普通通过只改审核状态。修改人:Ld 修改时间:2026-07-17 09:10:08;
param.push(['审核完成数量', editData.finishQuantity])

File diff suppressed because it is too large Load Diff

View File

@@ -67,7 +67,7 @@
style="margin-left: 10px"
@click="CancelUrgent()">取消加急
</el-button>
<el-button type="success" plain size="small" style="margin-left: 10px" @click="getNum()">查看图纸
<el-button type="success" plain size="small" style="margin-left: 10px" @click="getNum()">查看图纸<!-- 修改人:Ld 修改时间:2026-08-12 09:37:10; 查看图纸改为使用当前选择零件的物料编码优先查询PLM。 -->
</el-button>
<el-button v-if="Number(token) === 2" type="danger" plain size="small" style="margin-left: 10px" @click="openScrapDialog()">手动报废结单
</el-button>
@@ -482,6 +482,7 @@ export default {
productionNum: '',
finishNum: '',
partTool: '',
selectedPartRow: null, // 修改人:Ld 修改时间:2026-08-12 09:37:10; 保存当前选择零件行,用于查看图纸时读取物料编码。
dateRange: '', // 提交日期
contractStateValue: '', // 合同状态
partNameValue: '', // 零件名称
@@ -653,7 +654,37 @@ export default {
console.log('WebSocket连接失败')
},
// 查看零件图
getNum() {
getNum() { // 修改人:Ld 修改时间:2026-08-12 09:37:10; 查看图纸先按选中物料编码查PLM,无有效链接时回落原图纸查询。
const row = this.selectedPartRow
if (!row) {
this.$message.warning('请先选择零件')
return
}
const msgId = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0
const v = c === 'x' ? r : (r & 0x3 | 0x8)
return v.toString(16)
})
request({
url: 'http://192.168.1.27:9982/api/GetMaterialDrawingUrl',
method: 'post',
data: {
msgId: msgId,
materialCode: row.物料编码
}
}).then(response => {
if (response.data && response.data.Code === '200' && response.data.Data && response.data.Data.url) {
window.open(response.data.Data.url, '_blank')
} else {
this.$message.warning('PLM未返回有效链接')
this.openLocalDrawing()
}
}).catch(() => {
this.$message.error('PLM请求发送失败')
this.openLocalDrawing()
})
},
openLocalDrawing() { // 修改人:Ld 修改时间:2026-08-12 09:37:10; PLM未获取有效链接时调用原本地查看图纸逻辑。
if (this.partTool) {
this.dialogVisible = true
this.getFileList(this.partTool)
@@ -785,6 +816,7 @@ export default {
})
},
searchTable1(row) {
this.selectedPartRow = row // 修改人:Ld 修改时间:2026-08-12 09:37:10; 记录查看图纸使用的当前选择物料编码。
this.partTool = row.零件图号
this.processValue = row.工艺计划流水号
this.IsItUrgent = Number(row.是否加急)

View File

@@ -197,6 +197,13 @@
</div>
<div style="margin: 12px 0">
<el-button type="primary" size="small" icon="el-icon-search" @click="previewInventoryImport">预校验</el-button>
<!-- 修改人:Ld 修改时间:2026-08-11 13:14:38; 新增导入盘点预校验结果导出按钮。 -->
<el-button
:disabled="inventoryImportData.length === 0"
type="success"
size="small"
icon="el-icon-download"
@click="exportInventoryImportPreview">导出预校验</el-button>
<el-button
:loading="inventoryImportSubmitting"
:disabled="inventoryImportData.length === 0"
@@ -327,6 +334,9 @@ import { ExecDatabase } from '@/main'
import { wsuri } from '@/utils/request'
import { mapGetters } from 'vuex'
import UploadExcelComponent from '@/views/TechnologyCenter/ImportBOM/UploadExcel/index.vue'
// 修改人:Ld 修改时间:2026-08-11 13:14:38; 复用前端 Excel 导出依赖生成导入盘点预校验结果文件。
import XLSX from 'xlsx'
import FileSaver from 'file-saver'
export default {
components: { UploadExcelComponent },
data() {
@@ -789,6 +799,44 @@ export default {
this.inventoryImportDetailChunks = this.buildInventoryImportDetailChunks(detail)
this.requestInventoryImportPreview(0, [])
},
// 修改人:Ld 修改时间:2026-08-11 13:14:38; 将导入盘点预校验表格前端导出为 Excel,便于提交前复核和留存。
exportInventoryImportPreview() {
if (this.inventoryImportData.length === 0) {
this.$message.warning('请先预校验导入盘点数据')
return
}
var data = []
data.push(['行号', '物料编号', '物料名称', '图号型号', '原库位', '调整后库位', '原库存', '导入库存', '盘点库存', '库存变化', '库位变化', '处理结果', '错误原因'])
for (let i = 0; i < this.inventoryImportData.length; i++) {
var row = this.inventoryImportData[i]
data.push([
row.导入序号,
row.物料编码,
row.物料名称,
row.图号或型号,
row.原货位名称,
row.调整后库位,
row.原库存,
row.导入库存,
row.盘点库存,
row.库存变化,
row.库位变化,
row.处理结果,
row.错误原因
])
}
var ws = XLSX.utils.aoa_to_sheet(data)
ws['!cols'] = [
{ wch: 8 }, { wch: 16 }, { wch: 22 }, { wch: 18 }, { wch: 14 },
{ wch: 16 }, { wch: 10 }, { wch: 10 }, { wch: 10 }, { wch: 10 },
{ wch: 10 }, { wch: 12 }, { wch: 30 }
]
var wb = XLSX.utils.book_new()
XLSX.utils.book_append_sheet(wb, ws, '预校验结果')
var wbout = XLSX.write(wb, { bookType: 'xlsx', bookSST: false, type: 'array' })
FileSaver.saveAs(new Blob([wbout], { type: 'application/octet-stream' }), '库存盘点预校验结果.xlsx')
this.$message.success('导出成功')
},
requestInventoryImportSubmit(index, result) {
if (index >= this.inventoryImportDetailChunks.length) {
this.inventoryImportData = result

View File

@@ -0,0 +1,624 @@
<template>
<div class="app-container outbound-order-page">
<!-- 修改人:Ld 修改时间:2026-08-25 17:02:01; 新增纯前端出库单展示页面,审批仅删除当前页面展示条目,不写入后端。 -->
<el-card class="outbound-card">
<div class="page-head">
<div>
<div class="page-title">出库单</div>
<div class="page-subtitle">根据出库记录生成页面展示单据,审批不影响原出库记录数据</div>
</div>
<div class="head-actions">
<el-button type="primary" size="small" icon="el-icon-refresh" plain @click="resetSearch">重置</el-button>
<el-button type="success" size="small" icon="el-icon-search" @click="pageCurrent=1;searchTable()">查询</el-button>
</div>
</div>
<el-row :gutter="12" class="summary-row">
<el-col :span="6">
<div class="summary-item summary-blue">
<div class="summary-label">待审批单据</div>
<div class="summary-value">{{ summary.待审批 }}</div>
</div>
</el-col>
<el-col :span="6">
<div class="summary-item summary-green">
<div class="summary-label">出库总数</div>
<div class="summary-value">{{ summary.出库总数 }}</div>
</div>
</el-col>
<el-col :span="6">
<div class="summary-item summary-orange">
<div class="summary-label">涉及订单</div>
<div class="summary-value">{{ summary.订单数 }}</div>
</div>
</el-col>
<el-col :span="6">
<div class="summary-item summary-gray">
<div class="summary-label">物料种类</div>
<div class="summary-value">{{ summary.物料种类 }}</div>
</div>
</el-col>
</el-row>
<div class="search-bar">
<el-select
v-model="typeValue"
class="search-control"
placeholder="类型"
size="small"
filterable
clearable
@change="pageCurrent=1;searchTable()">
<el-option
v-for="item in type"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
<el-input
v-model="production"
class="search-wide"
size="small"
clearable
placeholder="物料名称/编号/规格/型号"
@keyup.enter.native="pageCurrent=1;searchTable()"/>
<el-select
v-model="pickListValue"
:remote-method="getList"
class="search-control"
size="small"
placeholder="领料单号"
filterable
clearable
remote
@change="pageCurrent=1;searchTable()">
<el-option
v-for="item in pickList"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
<el-select
v-model="pickPeopleValue"
class="search-control"
size="small"
placeholder="领料人"
filterable
clearable
@change="pageCurrent=1;searchTable()">
<el-option
v-for="item in pickPeople"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
<el-date-picker
v-model="dateRange"
size="small"
type="daterange"
align="center"
class="search-date"
value-format="yyyy-MM-dd"
format="yyyy-MM-dd"
range-separator="~"
start-placeholder="开始时间"
end-placeholder="结束时间"
@change="pageCurrent=1;searchTable()"/>
</div>
<el-table
v-loading="loading"
ref="table"
:data="tableData"
highlight-current-row
border
stripe
size="small"
class="order-table"
height="600px">
<el-table-column width="148px" label="出库单号" align="center" fixed show-overflow-tooltip>
<template slot-scope="scope">
<span class="order-code">{{ scope.row.出库单号 }}</span>
</template>
</el-table-column>
<el-table-column width="86px" label="审批状态" align="center" fixed>
<template slot-scope="scope">
<el-tag size="mini" type="warning">{{ scope.row.审批状态 }}</el-tag>
</template>
</el-table-column>
<el-table-column width="72px" label="类型" align="center">
<template slot-scope="scope">{{ scope.row.类型 }}</template>
</el-table-column>
<el-table-column width="150px" label="物料名称" align="center" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.物料名称 }}</template>
</el-table-column>
<el-table-column width="130px" label="物料编号" align="center" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.物料编码 }}</template>
</el-table-column>
<el-table-column width="145px" label="图号/型号" align="center" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.图号或型号 }}</template>
</el-table-column>
<el-table-column width="58px" label="单位" align="center">
<template slot-scope="scope">{{ scope.row.单位 }}</template>
</el-table-column>
<el-table-column width="82px" label="出库数量" align="center" prop="领料数">
<template slot-scope="scope">
<span class="number-text">{{ scope.row.领料数 }}</span>
</template>
</el-table-column>
<el-table-column width="95px" label="库位" align="center" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.库位 }}</template>
</el-table-column>
<el-table-column width="102px" label="出库日期" align="center">
<template slot-scope="scope">{{ scope.row.领料日期 }}</template>
</el-table-column>
<el-table-column width="86px" label="领料人" align="center">
<template slot-scope="scope">{{ scope.row.领料人 }}</template>
</el-table-column>
<el-table-column width="110px" label="领料单号" align="center" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.领料单号 }}</template>
</el-table-column>
<el-table-column width="128px" label="订单号" align="center" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.订单号 }}</template>
</el-table-column>
<el-table-column width="150px" label="产品/部件名称" align="center" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.产品名称 }}</template>
</el-table-column>
<el-table-column width="150px" label="批次编码" align="center" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.批次编码 }}</template>
</el-table-column>
<el-table-column min-width="160px" label="备注" align="center" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.备注 }}</template>
</el-table-column>
<el-table-column width="128px" label="操作" align="center" fixed="right">
<template slot-scope="scope">
<el-button type="primary" size="mini" plain @click="openApprove(scope.row)">审批</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-wrap">
<el-pagination
:current-page="pageCurrent"
:page-sizes="[10, 20, 30, 40, 100]"
:page-size="pageSize"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChanges"
@current-change="handleCurrentChanges"/>
</div>
</el-card>
<el-dialog v-el-drag-dialog :visible.sync="approveDialogVisible" title="出库单审批" center width="520px">
<div v-if="currentRow" class="approve-box">
<div class="approve-title">{{ currentRow.出库单号 }}</div>
<el-row :gutter="10">
<el-col :span="12">
<div class="approve-field">
<span>物料名称</span>
<strong>{{ currentRow.物料名称 }}</strong>
</div>
</el-col>
<el-col :span="12">
<div class="approve-field">
<span>出库数量</span>
<strong>{{ currentRow.领料数 }} {{ currentRow.单位 }}</strong>
</div>
</el-col>
<el-col :span="12">
<div class="approve-field">
<span>领料人</span>
<strong>{{ currentRow.领料人 }}</strong>
</div>
</el-col>
<el-col :span="12">
<div class="approve-field">
<span>出库日期</span>
<strong>{{ currentRow.领料日期 }}</strong>
</div>
</el-col>
</el-row>
<el-input
v-model="approvalRemark"
:rows="3"
type="textarea"
resize="none"
placeholder="审批意见"/>
<div class="approve-tip">审批后仅从当前出库单页面移除,不保存审批结果,不影响出库记录。</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button size="small" @click="approveDialogVisible=false">取消</el-button>
<el-button size="small" type="danger" plain @click="finishApproval('驳回')">驳回</el-button>
<el-button size="small" type="success" @click="finishApproval('通过')">通过</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
data() {
return {
typeValue: '',
type: [{
label: '自制',
value: '自制'
}, {
label: '外购',
value: '外购'
}, {
label: '耗材',
value: '耗材'
}, {
label: '通用',
value: '通用'
}, {
label: '临时',
value: '临时'
}, {
label: '备货',
value: '备货'
}],
pickList: [],
pickListValue: '',
pickPeople: [],
pickPeopleValue: '',
dateRange: '',
production: '',
loading: false,
total: 0,
tableData: [],
pageCurrent: 1,
pageSize: 100,
approveDialogVisible: false,
currentRow: null,
approvalRemark: ''
}
},
computed: {
...mapGetters([
'id'
]),
summary() {
var orderMap = {}
var materialMap = {}
var outTotal = 0
for (let i = 0; i < this.tableData.length; i++) {
var row = this.tableData[i]
if (row.订单号) {
orderMap[row.订单号] = true
}
if (row.物料编码 || row.物料名称) {
materialMap[(row.物料编码 || '') + row.物料名称] = true
}
outTotal += Number(row.领料数) || 0
}
return {
待审批: this.tableData.length,
出库总数: outTotal,
订单数: Object.keys(orderMap).length,
物料种类: Object.keys(materialMap).length
}
}
},
updated() {
this.$nextTick(() => {
if (this.$refs['table']) {
this.$refs['table'].doLayout()
}
})
},
created() {
this.fetchData()
this.searchTable()
},
methods: {
fetchData() {
this.getList('')
this.getPeople()
},
getList(query) {
var param = []
this.pickList = []
param[0] = ['领料单号', query]
var Data = this.CreateData('11', '仓库管理_领料单_查询_BAK', param)
this.ExecDatabase(Data).then(response => {
for (let i = 0; i < response.data.length; i++) {
this.pickList.push({
label: response.data[i].领料单号,
value: response.data[i].领料单号
})
}
})
},
getPeople() {
var param = []
var Data = this.CreateData('11', '仓库管理_领料人_查询', param)
this.ExecDatabase(Data).then(response => {
for (let i = 0; i < response.data.length; i++) {
this.pickPeople.push({
label: response.data[i].领料人,
value: response.data[i].领料人
})
}
})
},
resetSearch() {
this.typeValue = ''
this.pickListValue = ''
this.pickPeopleValue = ''
this.dateRange = ''
this.production = ''
this.pageCurrent = 1
this.searchTable()
},
searchTable() {
let dateRangeCheck, productionCheck, pickPeopleValueCheck, pickListValueCheck, typeValueCheck
this.typeValue ? typeValueCheck = 1 : typeValueCheck = 0
this.dateRange ? dateRangeCheck = 1 : dateRangeCheck = 0
this.production ? productionCheck = 1 : productionCheck = 0
this.pickListValue ? pickListValueCheck = 1 : pickListValueCheck = 0
this.pickPeopleValue ? pickPeopleValueCheck = 1 : pickPeopleValueCheck = 0
var startTime = this.dateRange ? this.dateRange[0] : ''
var endTime = this.dateRange ? this.dateRange[1] : ''
var param = []
param[0] = ['物料名称_check', productionCheck]
param[1] = ['物料名称', this.production]
param[2] = ['订单_check', 0]
param[3] = ['订单流水号', '']
param[4] = ['产品_check', 0]
param[5] = ['组件流水号', '']
param[6] = ['出库时间_check', dateRangeCheck]
param[7] = ['开始时间', startTime]
param[8] = ['结束时间', endTime]
param[9] = ['领料单_check', pickListValueCheck]
param[10] = ['领料单号', this.pickListValue]
param[11] = ['领料人_check', pickPeopleValueCheck]
param[12] = ['领料人', this.pickPeopleValue]
param[13] = ['退料_check', 0]
param[14] = ['类型_check', typeValueCheck]
param[15] = ['类型', this.typeValue]
var Data = this.CreateData('11', '仓储管理_出库记录_查询', param, this.pageSize, this.pageCurrent)
this.loading = true
this.ExecDatabase(Data).then(response => {
var rows = response.data.rows || []
this.tableData = this.buildDisplayRows(rows)
this.total = response.data.total || this.tableData.length
this.loading = false
}).catch(() => {
this.loading = false
this.$message.warning('出库单展示数据加载失败')
})
},
buildDisplayRows(rows) {
var displayRows = []
for (let i = 0; i < rows.length; i++) {
var row = Object.assign({}, rows[i])
row.出库单号 = this.createOrderCode(row, i)
row.审批状态 = '待审批'
displayRows.push(row)
}
return displayRows
},
createOrderCode(row, index) {
var dateText = (row.领料日期 || '').replace(/-/g, '')
if (!dateText) {
dateText = this.formatDate(new Date()).replace(/-/g, '')
}
var serial = row.出库记录流水号 || (this.pageCurrent + '-' + index)
return 'CKD-' + dateText + '-' + serial
},
formatDate(date) {
var month = date.getMonth() + 1
var day = date.getDate()
return date.getFullYear() + '-' + (month < 10 ? '0' + month : month) + '-' + (day < 10 ? '0' + day : day)
},
openApprove(row) {
this.currentRow = row
this.approvalRemark = ''
this.approveDialogVisible = true
},
finishApproval(result) {
if (!this.currentRow) {
return
}
this.$confirm('确认审批' + result + '?审批后该条仅从当前页面移除。', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
var orderCode = this.currentRow.出库单号
this.tableData = this.tableData.filter(function(item) {
return item.出库单号 !== orderCode
})
this.total = this.total > 0 ? this.total - 1 : 0
this.approveDialogVisible = false
this.currentRow = null
this.$message.success('审批' + result + ',已从当前展示列表移除')
}).catch(() => {
this.$message({
type: 'info',
message: '已取消审批'
})
})
},
handleSizeChanges(val) {
this.pageCurrent = 1
this.pageSize = val
this.searchTable()
},
handleCurrentChanges(val) {
this.pageCurrent = val
this.searchTable()
}
}
}
</script>
<style scoped>
.outbound-order-page {
background: #f5f7fb;
}
.outbound-card {
min-height: 850px;
border: 0;
}
.page-head {
display: flex;
align-items: center;
justify-content: space-between;
padding: 4px 2px 16px;
border-bottom: 1px solid #ebeef5;
}
.page-title {
color: #1f2d3d;
font-size: 22px;
font-weight: 600;
line-height: 30px;
}
.page-subtitle {
margin-top: 4px;
color: #7a8499;
font-size: 13px;
}
.head-actions {
display: flex;
align-items: center;
}
.summary-row {
margin-top: 14px;
}
.summary-item {
height: 78px;
padding: 14px 18px;
border: 1px solid #ebeef5;
border-radius: 6px;
background: #fff;
}
.summary-label {
color: #6b7280;
font-size: 13px;
}
.summary-value {
margin-top: 8px;
color: #202b3c;
font-size: 28px;
font-weight: 600;
line-height: 32px;
}
.summary-blue {
border-left: 4px solid #409eff;
}
.summary-green {
border-left: 4px solid #67c23a;
}
.summary-orange {
border-left: 4px solid #e6a23c;
}
.summary-gray {
border-left: 4px solid #909399;
}
.search-bar {
display: flex;
align-items: center;
flex-wrap: wrap;
padding: 14px 0 12px;
}
.search-control {
width: 150px;
margin-right: 10px;
margin-bottom: 8px;
}
.search-wide {
width: 240px;
margin-right: 10px;
margin-bottom: 8px;
}
.search-date {
width: 250px;
margin-bottom: 8px;
}
.order-table {
width: 100%;
}
.order-code {
color: #1f5fae;
font-weight: 600;
}
.number-text {
color: #303133;
font-weight: 600;
}
.pagination-wrap {
margin-top: 12px;
text-align: right;
}
.approve-box {
padding: 4px 8px 0;
}
.approve-title {
margin-bottom: 12px;
color: #1f2d3d;
font-size: 18px;
font-weight: 600;
}
.approve-field {
margin-bottom: 12px;
padding: 10px 12px;
border: 1px solid #ebeef5;
border-radius: 6px;
background: #fafbfc;
}
.approve-field span {
display: block;
color: #8a94a6;
font-size: 12px;
line-height: 18px;
}
.approve-field strong {
display: block;
overflow: hidden;
margin-top: 4px;
color: #303133;
font-size: 14px;
font-weight: 600;
line-height: 20px;
text-overflow: ellipsis;
white-space: nowrap;
}
.approve-tip {
margin-top: 10px;
color: #909399;
font-size: 12px;
line-height: 18px;
}
</style>

View File

@@ -0,0 +1,675 @@
<template>
<!-- 修改人:Ld 修改时间:2026-09-08 10:04:25; 新增仓库PDA采购扫码入库页面 -->
<div class="app-container pda-purchase-inbound">
<el-card class="pda-shell">
<div class="pda-header">
<div>
<div class="pda-title">PDA采购扫码入库</div>
<div class="pda-subtitle">{{ currentLabelText }}</div>
</div>
<el-tag :type="labelStateType" size="small">{{ labelStateText }}</el-tag>
</div>
<div class="scan-panel">
<el-input
ref="scanInput"
v-model="scanContent"
class="scan-input"
size="medium"
clearable
placeholder="扫描或输入入库标签二维码"
prefix-icon="el-icon-full-screen"
@keyup.enter.native="scanLabel"/>
<el-button
:loading="loading"
class="scan-button"
type="primary"
icon="el-icon-search"
size="medium"
@click="scanLabel">
查询
</el-button>
</div>
<div class="summary-grid">
<div class="summary-item">
<span>入库单号</span>
<strong>{{ labelInfo.入库单号 || '-' }}</strong>
</div>
<div class="summary-item">
<span>采购合同号</span>
<strong>{{ labelInfo.采购合同号 || labelInfo.采购合同 || '-' }}</strong>
</div>
<div class="summary-item">
<span>供应商</span>
<strong>{{ labelInfo.供应商 || '-' }}</strong>
</div>
<div class="summary-item">
<span>待入库数量</span>
<strong>{{ remainingTotal }}</strong>
</div>
</div>
<div class="batch-location">
<el-select
v-model="batchLocationValue"
:remote-method="getLocationOptions"
:loading="locationLoading"
class="batch-location-select"
size="medium"
filterable
remote
clearable
reserve-keyword
placeholder="批量选择货位">
<el-option
v-for="item in locationOptions"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
<el-button
:disabled="detailRows.length === 0 || !batchLocationValue"
class="batch-location-button"
type="success"
plain
icon="el-icon-location-outline"
size="medium"
@click="applyBatchLocation">
应用货位
</el-button>
</div>
<div v-loading="loading" class="detail-area">
<el-empty v-if="detailRows.length === 0" description="请先扫描入库标签"/>
<div v-else class="detail-list">
<div v-for="(item, index) in detailRows" :key="getRowKey(item, index)" class="detail-card">
<div class="card-top">
<el-checkbox v-model="item.选中" :disabled="getRemainingCount(item) <= 0"/>
<div class="material-info">
<div class="material-name">{{ item.物料名称 || '-' }}</div>
<div class="material-code">图号:{{ item.图号 || item.图号型号 || '-' }}</div>
</div>
<el-tag :type="getRowStateType(item)" size="mini">{{ getRowStateText(item) }}</el-tag>
</div>
<div class="number-grid">
<div>
<span>标签数量</span>
<strong>{{ formatNumber(item.标签数量 || item.数量) }}</strong>
</div>
<div>
<span>已入库</span>
<strong>{{ formatNumber(item.已入库数量) }}</strong>
</div>
<div>
<span>剩余</span>
<strong>{{ formatNumber(getRemainingCount(item)) }}</strong>
</div>
</div>
<div class="card-form">
<div class="form-item">
<span>本次入库数量</span>
<el-input-number
v-model="item.本次入库数量"
:min="0"
:max="getRemainingCount(item)"
:precision="4"
:controls="false"
size="medium"
@change="onQuantityChange(item)"/>
</div>
<div class="form-item">
<span>货位</span>
<el-select
v-model="item.货位流水号"
:remote-method="getLocationOptions"
:loading="locationLoading"
size="medium"
filterable
remote
clearable
reserve-keyword
placeholder="扫描或选择货位"
@change="onLocationChange(item)">
<el-option
v-for="location in locationOptions"
:key="location.value"
:label="location.label"
:value="location.value"/>
</el-select>
</div>
</div>
<div class="card-bottom">
<span>批次号:{{ item.批次号 || item.批号 || '-' }}</span>
<span>批次编码:{{ item.批次编码 || '-' }}</span>
</div>
</div>
</div>
</div>
</el-card>
<div class="bottom-actions">
<el-button size="medium" icon="el-icon-refresh-left" @click="resetPage">清空</el-button>
<el-button
:disabled="submitDisabled"
:loading="submitLoading"
type="primary"
size="medium"
icon="el-icon-check"
@click="submitInbound">
确认入库
</el-button>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'PDAPurchaseInbound',
data() {
return {
loading: false,
submitLoading: false,
locationLoading: false,
scanContent: '',
labelInfo: {},
detailRows: [],
locationOptions: [],
batchLocationValue: ''
}
},
computed: {
...mapGetters([
'id',
'token'
]),
currentLabelText() {
if (this.labelInfo.标签编号) {
return this.labelInfo.标签编号
}
return '请扫描入库单标签二维码'
},
labelStateText() {
if (this.detailRows.length === 0) {
return '待扫码'
}
if (this.remainingTotal <= 0) {
return '已完成'
}
return '待入库'
},
labelStateType() {
if (this.detailRows.length === 0) {
return 'info'
}
if (this.remainingTotal <= 0) {
return 'success'
}
return 'warning'
},
remainingTotal() {
var total = 0
this.detailRows.forEach(item => {
total += Number(this.getRemainingCount(item) || 0)
})
return Number(total.toFixed(4))
},
submitDisabled() {
return this.submitRows().length === 0
}
},
mounted() {
// 修改人:Ld 修改时间:2026-09-08 10:04:25; PDA页面进入后自动聚焦扫码框并覆盖全局最小宽度。
document.body.classList.add('pda-purchase-inbound-page')
this.focusScanInput()
this.getLocationOptions('')
},
beforeDestroy() {
document.body.classList.remove('pda-purchase-inbound-page')
},
methods: {
focusScanInput() {
this.$nextTick(() => {
if (this.$refs.scanInput) {
this.$refs.scanInput.focus()
}
})
},
// 修改人:Ld 修改时间:2026-09-08 10:04:25; 调用PDA扫码查询过程加载标签头和明细。
scanLabel() {
if (!this.scanContent) {
this.$message.warning('请先扫描或输入标签二维码')
this.focusScanInput()
return
}
this.loading = true
var param = []
param[0] = ['扫码内容', this.scanContent]
param[1] = ['标签ID', '']
param[2] = ['入库单号', '']
var Data = this.CreateData('11', '仓储管理_PDA采购扫码入库_查询', param)
this.ExecDatabase(Data).then(response => {
var data = response.data.rows || response.data || []
this.setScanResult(data)
if (this.detailRows.length === 0) {
this.$message.warning('未查询到该标签明细')
}
}).catch(() => {
this.$message.error('扫码查询失败')
}).finally(() => {
this.loading = false
})
},
setScanResult(data) {
var firstRow = data.length > 0 ? data[0] : {}
this.labelInfo = Object.assign({}, firstRow)
this.detailRows = data.map(item => {
var remainingCount = Number(item.剩余入库数量 || item.剩余数量 || 0)
return Object.assign({}, item, {
选中: remainingCount > 0,
本次入库数量: remainingCount > 0 ? remainingCount : 0,
货位流水号: item.货位流水号 || '',
货位名称: item.货位名称 || ''
})
})
this.batchLocationValue = ''
},
// 修改人:Ld 修改时间:2026-09-08 10:04:25; 货位采用远程模糊查询,支持PDA扫描货位码后快速选择。
getLocationOptions(query) {
this.locationLoading = true
var param = []
param[0] = ['货位名称', query || '']
var Data = this.CreateData('11', '仓储管理_PDA货位_查询', param)
this.ExecDatabase(Data).then(response => {
var data = response.data.rows || response.data || []
this.locationOptions = data.map(function(item) {
return {
label: item.货位名称,
value: item.货位流水号
}
})
}).finally(() => {
this.locationLoading = false
})
},
applyBatchLocation() {
var selected = this.locationOptions.find(item => {
return item.value === this.batchLocationValue
})
this.detailRows.forEach(item => {
if (item.选中 && this.getRemainingCount(item) > 0) {
item.货位流水号 = this.batchLocationValue
item.货位名称 = selected ? selected.label : item.货位名称
}
})
},
onLocationChange(row) {
var selected = this.locationOptions.find(item => {
return item.value === row.货位流水号
})
row.货位名称 = selected ? selected.label : ''
},
onQuantityChange(row) {
if (Number(row.本次入库数量) > 0) {
row.选中 = true
}
if (Number(row.本次入库数量) === 0) {
row.选中 = false
}
},
submitRows() {
return this.detailRows.filter(item => {
return item.选中 && Number(item.本次入库数量) > 0
})
},
// 修改人:Ld 修改时间:2026-09-08 10:04:25; 提交时按明细、数量、货位三个数组传给测试库PDA入库过程。
submitInbound() {
var rows = this.submitRows()
if (rows.length === 0) {
this.$message.warning('请至少选择一条待入库明细')
return
}
for (let i = 0; i < rows.length; i++) {
if (!rows[i].货位流水号) {
this.$message.warning('请选择货位')
return
}
if (Number(rows[i].本次入库数量) > this.getRemainingCount(rows[i])) {
this.$message.warning('入库数量不能大于剩余数量')
return
}
}
this.submitLoading = true
var param = []
param[0] = ['扫码内容', this.scanContent]
param[1] = ['标签ID', this.labelInfo.标签ID || '']
param[2] = ['标签明细流水号组', rows.map(function(item) { return item.标签明细流水号 || item.明细流水号 }).join(',')]
param[3] = ['入库数量组', rows.map(function(item) { return item.本次入库数量 }).join(',')]
param[4] = ['货位流水号组', rows.map(function(item) { return item.货位流水号 }).join(',')]
param[5] = ['入库人', this.id]
var Data = this.CreateData('12', '仓储管理_PDA采购扫码入库_提交', param)
this.ExecDatabase(Data).then(response => {
var result = response.data && response.data.length > 0 ? response.data[0] : {}
if (String(result.result) === '1') {
this.$message.success(result.message || '入库成功')
this.scanLabel()
} else {
this.$message.error(result.message || '入库失败')
}
}).catch(() => {
this.$message.error('提交失败,请重试')
}).finally(() => {
this.submitLoading = false
})
},
resetPage() {
this.scanContent = ''
this.labelInfo = {}
this.detailRows = []
this.batchLocationValue = ''
this.focusScanInput()
},
getRemainingCount(row) {
var value = row.剩余入库数量
if (value === undefined || value === null || value === '') {
value = Number(row.标签数量 || row.数量 || 0) - Number(row.已入库数量 || 0)
}
value = Number(value || 0)
return value > 0 ? value : 0
},
getRowKey(row, index) {
return row.标签明细流水号 || row.明细流水号 || index
},
getRowStateText(row) {
if (Number(row.入库状态) === 2 || this.getRemainingCount(row) <= 0) {
return '已完成'
}
if (Number(row.入库状态) === 1) {
return '部分入库'
}
return '待入库'
},
getRowStateType(row) {
if (Number(row.入库状态) === 2 || this.getRemainingCount(row) <= 0) {
return 'success'
}
if (Number(row.入库状态) === 1) {
return 'warning'
}
return 'info'
},
formatNumber(value) {
var numberValue = Number(value || 0)
return Number(numberValue.toFixed(4))
}
}
}
</script>
<style scoped>
/* 修改人:Ld 修改时间:2026-09-08 10:04:25; PDA采购扫码入库页面窄屏触控样式 */
.pda-purchase-inbound,
.pda-purchase-inbound * {
box-sizing: border-box;
}
.pda-purchase-inbound {
width: 100%;
min-height: calc(100vh - 84px);
padding: 10px 10px 76px;
overflow-x: hidden;
background: #f3f6fb;
}
.pda-shell {
min-height: calc(100vh - 150px);
border-radius: 6px;
}
.pda-shell >>> .el-card__body {
padding: 12px !important;
}
.pda-header,
.scan-panel,
.batch-location,
.card-top,
.card-bottom {
display: flex;
align-items: center;
gap: 10px;
}
.pda-header {
justify-content: space-between;
margin-bottom: 12px;
}
.pda-title {
font-size: 20px;
font-weight: 700;
color: #1f2d3d;
}
.pda-subtitle {
max-width: 260px;
margin-top: 4px;
overflow: hidden;
font-size: 12px;
color: #8492a6;
text-overflow: ellipsis;
white-space: nowrap;
}
.scan-panel,
.batch-location {
margin-bottom: 10px;
}
.scan-input,
.batch-location-select {
flex: 1;
min-width: 0;
}
.scan-button,
.batch-location-button {
width: 96px;
flex: 0 0 96px;
}
.summary-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 8px;
margin-bottom: 10px;
}
.summary-item {
min-width: 0;
padding: 9px 10px;
border: 1px solid #dcdfe6;
border-radius: 6px;
background: #fff;
}
.summary-item span {
display: block;
margin-bottom: 5px;
color: #909399;
font-size: 12px;
}
.summary-item strong {
display: block;
min-width: 0;
overflow: hidden;
color: #303133;
font-size: 16px;
text-overflow: ellipsis;
white-space: nowrap;
}
.detail-list {
display: grid;
grid-template-columns: repeat(2, minmax(260px, 1fr));
gap: 10px;
}
.detail-card {
min-width: 0;
padding: 12px;
border: 1px solid #dcdfe6;
border-radius: 6px;
background: #fff;
}
.card-top {
align-items: flex-start;
}
.material-info {
flex: 1;
min-width: 0;
}
.material-name {
min-width: 0;
overflow: hidden;
color: #303133;
font-size: 16px;
font-weight: 700;
text-overflow: ellipsis;
white-space: nowrap;
}
.material-code,
.card-bottom {
color: #606266;
font-size: 12px;
}
.number-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 8px;
margin: 10px 0;
}
.number-grid div {
min-width: 0;
padding: 8px;
border-radius: 4px;
background: #f5f7fa;
}
.number-grid span,
.form-item span {
display: block;
margin-bottom: 5px;
color: #909399;
font-size: 12px;
}
.number-grid strong {
display: block;
color: #303133;
font-size: 16px;
}
.card-form {
display: grid;
grid-template-columns: minmax(120px, 160px) minmax(160px, 1fr);
gap: 10px;
}
.form-item {
min-width: 0;
}
.pda-purchase-inbound >>> .el-select,
.pda-purchase-inbound >>> .el-input,
.pda-purchase-inbound >>> .el-input-number,
.pda-purchase-inbound >>> .el-button {
width: 100%;
max-width: 100%;
min-width: 0;
}
.pda-purchase-inbound >>> .el-input__inner {
height: 40px;
min-width: 0;
font-size: 15px;
}
.card-bottom {
justify-content: space-between;
margin-top: 10px;
}
.card-bottom span {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.bottom-actions {
position: fixed;
right: 16px;
bottom: 14px;
left: 16px;
z-index: 10;
display: grid;
grid-template-columns: 96px 1fr;
gap: 10px;
padding: 10px;
border: 1px solid #dcdfe6;
border-radius: 6px;
background: #fff;
box-shadow: 0 8px 24px rgba(31, 45, 61, 0.14);
}
@media (max-width: 760px) {
.pda-purchase-inbound {
padding: 8px 8px 74px;
}
.summary-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.detail-list,
.card-form {
grid-template-columns: 1fr;
}
.scan-panel,
.batch-location {
align-items: stretch;
flex-direction: column;
}
.scan-button,
.batch-location-button {
width: 100%;
flex-basis: auto;
}
}
</style>
<style>
/* 修改人:Ld 修改时间:2026-09-08 10:04:25; PDA页面覆盖后台布局最小宽度,适配手持终端 */
body.pda-purchase-inbound-page {
min-width: 0 !important;
}
body.pda-purchase-inbound-page .app-main {
min-width: 0 !important;
}
</style>

View File

@@ -1,6 +1,7 @@
<template>
<div class="app-container">
<el-card style="height: 850px ;display:flex">
<!-- 修改人:Ld 修改时间:2026-08-11 09:14:50; 为报缺补货页面增加专用作用域类,避免样式影响其他组件布局。 -->
<div class="app-container replenishment-page">
<el-card class="replenishment-card" style="height: 850px ;display:flex">
<el-col style="width: 930px">
<div style="margin-top: 7px; margin-bottom: 7px">
<el-cascader ref="cascader" :options="product" :show-all-levels="false" placeholder="产品名称" clearable size="small" @clear="clearData" @change="getData"/>
@@ -284,8 +285,9 @@
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="small" @click="dialogFormVisibleLink=false">取 消</el-button>
<el-button type="primary" size="small" @click="submitLinkedOrder">确 定</el-button>
<el-button :disabled="linkSubmitting" size="small" @click="dialogFormVisibleLink=false">取 消</el-button>
<!-- 修改人:Ld 修改时间:2026-08-11 09:42:28; 关联合同补货提交期间禁用确认按钮,避免重复点击生成多张订单。 -->
<el-button :loading="linkSubmitting" :disabled="linkSubmitting" type="primary" size="small" @click="submitLinkedOrder">确 定</el-button>
</div>
</el-dialog>
<el-dialog v-el-drag-dialog :visible.sync="dialogFormVisible2" title="上传图片" center style="height: 800px" width="30%">
@@ -403,6 +405,7 @@ export default {
// 修改人:Ld 修改时间:2026-08-03 16:35:25; 关联合同补货弹窗数据,独立于原补货提交。
dialogFormVisibleLink: false,
linkContractLoading: false,
linkSubmitting: false, // 修改人:Ld 修改时间:2026-08-11 09:42:28; 关联合同补货提交中状态,用于防止重复提交。
linkContractList: [],
linkForm: {
来源类型: '合同缺件',
@@ -657,6 +660,10 @@ export default {
},
// 修改人:Ld 修改时间:2026-08-03 16:35:25; 提交带合同/仓库备货来源的补货单,原 submitOrder 不变。
submitLinkedOrder() {
// 修改人:Ld 修改时间:2026-08-11 09:42:28; 请求未返回前直接拦截后续提交,避免同一补货单重复生成订单。
if (this.linkSubmitting) {
return
}
if (this.linkForm.来源类型 === '合同缺件' && !this.linkForm.项目流水号) {
this.$message.warning('请选择关联销售合同')
return
@@ -680,6 +687,7 @@ export default {
param[5] = ['项目流水号', this.linkForm.项目流水号 || 0]
param[6] = ['订单流水号', this.linkForm.订单流水号 || 0]
var Data = this.CreateData('12', '报缺补货_提交_关联合同', param)
this.linkSubmitting = true
this.ExecDatabase(Data).then(response => {
if (response.data[0].result === '1') {
this.$message.success('提交成功')
@@ -688,6 +696,9 @@ export default {
} else {
this.$message.error(response.data[0].message || '提交失败')
}
this.linkSubmitting = false
}).catch(() => {
this.linkSubmitting = false
})
},
selectIn(row) {
@@ -917,25 +928,26 @@ export default {
}
</script>
<style>
.is-rotate {
/* 修改人:Ld 修改时间:2026-08-11 09:14:50; 限定报缺补货页面样式作用域,避免全局 el-card__body flex 导致其他页面表格偏移。 */
.replenishment-page .is-rotate {
-webkit-transform: rotate(180deg);
-moz-transform: rotate(180deg);
-o-transform: rotate(180deg);
-ms-transform: rotate(180deg);
transform: rotate(180deg);
}
.Outsourcing {
.replenishment-page .Outsourcing {
background: #D9FFFF!important;
}
.red {
.replenishment-page .red {
color: #e88383!important;
font-weight: bold;
}
.yellow {
.replenishment-page .yellow {
color: orange!important;
font-weight: bold;
}
.el-card__body{
.replenishment-page .replenishment-card > .el-card__body{
display: flex;
}