Browse Source

生产委外领料页面修改

master
shenzhouyu 7 months ago
parent
commit
77304da7aa
  1. 63
      src/views/modules/outsourcing-issue/DirectIssue.vue
  2. 63
      src/views/modules/outsourcing-issue/index.vue
  3. 549
      src/views/modules/production-issue/productionIssuePda.vue

63
src/views/modules/outsourcing-issue/DirectIssue.vue

@ -1,7 +1,14 @@
<template> <template>
<div>
<div class="status-bar">
<div class="goBack" @click="handleBack"><i class="el-icon-arrow-left"></i>上一页</div>
<div class="goBack">{{ functionTitle }}</div>
<div class="network" style="color: #fff" @click="$router.push({ path: '/' })">🏠首页</div>
</div>
<div class="input-section"> <div class="input-section">
<!-- PO号输入 --> <!-- PO号输入 -->
<div class="input-group" v-if="!materialList.length">
<div v-if="processFlag === 1">
<div class="input-group">
<div class="input-group"> <div class="input-group">
<label>PO号</label> <label>PO号</label>
<div class="input-with-scan"> <div class="input-with-scan">
@ -12,16 +19,11 @@
<button @click="loadMaterials" class="scan-btn">确认</button> <button @click="loadMaterials" class="scan-btn">确认</button>
</div> </div>
</div> </div>
<!-- 物料列表 -->
<div class="materials-section" v-if="materialList.length"> <div class="materials-section" v-if="materialList.length">
<div class="section-header">
<h3>PO物料 ({{ poNo }})</h3>
<button @click="resetPO" class="reset-btn">重新选择</button>
</div>
<div class="material-list"> <div class="material-list">
<div v-for="(material, index) in materialList" :key="index" class="material-item" <div v-for="(material, index) in materialList" :key="index" class="material-item"
:class="{ selected: selectedMaterial && selectedMaterial.partNo === material.partNo }" :class="{ selected: selectedMaterial && selectedMaterial.partNo === material.partNo }"
@click="selectMaterial(material)">
@click="goToDetail(material)">
<div class="material-info"> <div class="material-info">
<div class="part-no">{{ material.partNo }}</div> <div class="part-no">{{ material.partNo }}</div>
<div class="part-desc">{{ material.desc }}</div> <div class="part-desc">{{ material.desc }}</div>
@ -36,35 +38,24 @@
</div> </div>
</div> </div>
</div> </div>
<!-- 扫描标签 -->
<div class="scan-section" v-if="selectedMaterial">
<div class="section-header">
<h3>扫描物料标签</h3>
</div> </div>
<div class="input-group">
<label>物料标签</label>
<div class="input-with-scan">
<input v-model="scannedLabel" placeholder="请扫描物料标签" @keyup.enter="parseMaterialLabel" />
<button @click="parseMaterialLabel" class="scan-btn">解析</button>
</div>
</div>
<!-- 标签信息 -->
<!-- 扫描标签/发料详情 -->
<div class="scan-section" v-if="processFlag === 2">
<div class="label-info" v-if="labelInfo"> <div class="label-info" v-if="labelInfo">
<div class="info-row"><span class="label">物料编码:</span><span class="value">{{ labelInfo.partNo }}</span></div> <div class="info-row"><span class="label">物料编码:</span><span class="value">{{ labelInfo.partNo }}</span></div>
<div class="info-row"><span class="label">批次号:</span><span class="value">{{ labelInfo.batchNo }}</span></div> <div class="info-row"><span class="label">批次号:</span><span class="value">{{ labelInfo.batchNo }}</span></div>
<div class="info-row"><span class="label">可用数量:</span><span class="value">{{ labelInfo.availableQty }}</span> <div class="info-row"><span class="label">可用数量:</span><span class="value">{{ labelInfo.availableQty }}</span>
</div> </div>
</div> </div>
<!-- 发料数量 -->
<div class="qty-input" v-if="labelInfo"> <div class="qty-input" v-if="labelInfo">
<div class="input-group"> <div class="input-group">
<label>发料数量</label> <label>发料数量</label>
<input v-model="issueQty" type="number" :max="Math.min(selectedMaterial.thisRecvQty, labelInfo.availableQty)"
placeholder="请输入发料数量" />
<input v-model="issueQty" type="number"
:max="Math.min(selectedMaterial.thisRecvQty, labelInfo.availableQty)" placeholder="请输入发料数量" />
</div> </div>
<div class="input-group"> <div class="input-group">
<label>备注</label> <label>备注</label>
<input v-model="remark" placeholder="可选" />
<el-input type="textarea" v-model="remark" placeholder="可选" />
</div> </div>
<button @click="confirmIssue" class="confirm-btn" :disabled="!issueQty">确认发料</button> <button @click="confirmIssue" class="confirm-btn" :disabled="!issueQty">确认发料</button>
</div> </div>
@ -72,13 +63,21 @@
<!-- 消息提示 --> <!-- 消息提示 -->
<div class="message" v-if="message" :class="messageType">{{ message }}</div> <div class="message" v-if="message" :class="messageType">{{ message }}</div>
</div> </div>
</div>
</template> </template>
<script> <script>
import { getPoList } from '@/api/po/po.js' import { getPoList } from '@/api/po/po.js'
export default { export default {
name: 'DirectIssue', name: 'DirectIssue',
props: {
functionTitle: {
type: String,
default: '',
},
},
data() { data() {
return { return {
processFlag: 1, // 1=PO, 2=, 3=/
poNo: '', poNo: '',
materialList: [], materialList: [],
selectedMaterial: null, selectedMaterial: null,
@ -91,6 +90,13 @@ export default {
} }
}, },
methods: { methods: {
handleBack() {
if (this.processFlag === 2) {
this.processFlag = 1
} else if (this.processFlag === 1) {
this.$emit('back')
}
},
async loadMaterials() { async loadMaterials() {
if (!this.poNo) { if (!this.poNo) {
this.showMessage('请输入PO号', 'error') this.showMessage('请输入PO号', 'error')
@ -111,15 +117,20 @@ export default {
this.showMessage('网络错误', 'error') this.showMessage('网络错误', 'error')
} }
}, },
selectMaterial(material) {
goToDetail(material) {
if (material.thisRecvQty <= 0) { if (material.thisRecvQty <= 0) {
this.showMessage('该物料已发料完成', 'warning') this.showMessage('该物料已发料完成', 'warning')
return return
} }
this.selectedMaterial = material this.selectedMaterial = material
this.scannedLabel = '' this.scannedLabel = ''
this.labelInfo = null
this.labelInfo = {
partNo: this.selectedMaterial.partNo,
batchNo: 'BATCH001',
availableQty: 100,
}
this.issueQty = null this.issueQty = null
this.processFlag = 2
}, },
resetPO() { resetPO() {
this.poNo = '' this.poNo = ''
@ -128,6 +139,7 @@ export default {
this.scannedLabel = '' this.scannedLabel = ''
this.labelInfo = null this.labelInfo = null
this.issueQty = null this.issueQty = null
this.processFlag = 1
}, },
parseMaterialLabel() { parseMaterialLabel() {
// TODO: APIlabelInfo // TODO: APIlabelInfo
@ -152,6 +164,7 @@ export default {
this.scannedLabel = '' this.scannedLabel = ''
this.labelInfo = null this.labelInfo = null
this.issueQty = null this.issueQty = null
this.processFlag = 1
}, },
showMessage(text, type = 'info') { showMessage(text, type = 'info') {
this.message = text this.message = text

63
src/views/modules/outsourcing-issue/index.vue

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<div class="pda-container"> <div class="pda-container">
<div class="status-bar">
<div class="status-bar" v-if="selectedFunction != 'direct'">
<div class="goBack" @click="goBack"><i class="el-icon-arrow-left"></i>上一页</div> <div class="goBack" @click="goBack"><i class="el-icon-arrow-left"></i>上一页</div>
<div class="goBack">{{ functionTitle }}</div> <div class="goBack">{{ functionTitle }}</div>
<div class="network" style="color: #fff" @click="$router.push({ path: '/' })">🏠首页</div> <div class="network" style="color: #fff" @click="$router.push({ path: '/' })">🏠首页</div>
@ -12,7 +12,7 @@
<div class="function-card" @click="selectFunction('direct')"> <div class="function-card" @click="selectFunction('direct')">
<div class="function-icon">📦</div> <div class="function-icon">📦</div>
<div class="function-title">直接发料</div> <div class="function-title">直接发料</div>
<div class="function-desc">输入工单/PO扫描物料标签直接发料</div>
<div class="function-desc">输入委外订单扫描物料标签直接发料</div>
</div> </div>
<div class="function-card" @click="selectFunction('picking')"> <div class="function-card" @click="selectFunction('picking')">
<div class="function-icon">🏗</div> <div class="function-icon">🏗</div>
@ -31,9 +31,7 @@
</div> </div>
</div> </div>
<!-- 直接发料骨架 --> <!-- 直接发料骨架 -->
<div v-if="selectedFunction === 'direct'">
<direct-issue @back="resetAll" />
</div>
<direct-issue v-if="selectedFunction === 'direct'" functionTitle="直接发料" @back="resetAll" />
<!-- 拣选装托盘骨架 --> <!-- 拣选装托盘骨架 -->
<div v-if="selectedFunction === 'picking'"> <div v-if="selectedFunction === 'picking'">
<picking-issue @back="resetAll" /> <picking-issue @back="resetAll" />
@ -63,22 +61,22 @@ export default {
DirectIssue, DirectIssue,
PickingIssue, PickingIssue,
MoveIssue, MoveIssue,
ReturnIssue
ReturnIssue,
}, },
data() { data() {
return { return {
selectedFunction: null
selectedFunction: null,
} }
}, },
computed: { computed: {
functionTitle() { functionTitle() {
if (!this.selectedFunction) return '委外发料';
if (this.selectedFunction === 'direct') return '直接发料';
if (this.selectedFunction === 'picking') return '拣选装托盘';
if (this.selectedFunction === 'move') return '移库发料';
if (this.selectedFunction === 'return') return '退料';
return '委外发料';
}
if (!this.selectedFunction) return '委外发料'
if (this.selectedFunction === 'direct') return '直接发料'
if (this.selectedFunction === 'picking') return '拣选装托盘'
if (this.selectedFunction === 'move') return '移库发料'
if (this.selectedFunction === 'return') return '退料'
return '委外发料'
},
}, },
methods: { methods: {
selectFunction(func) { selectFunction(func) {
@ -93,8 +91,8 @@ export default {
} else { } else {
this.selectedFunction = null this.selectedFunction = null
} }
}
}
},
},
} }
</script> </script>
@ -115,14 +113,14 @@ export default {
background: white; background: white;
border-radius: 8px; border-radius: 8px;
padding: 20px; padding: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
cursor: pointer; cursor: pointer;
transition: all 0.3s; transition: all 0.3s;
text-align: center; text-align: center;
} }
.function-card:hover { .function-card:hover {
transform: translateY(-2px); transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
} }
.function-icon { .function-icon {
font-size: 48px; font-size: 48px;
@ -138,4 +136,33 @@ export default {
font-size: 14px; font-size: 14px;
color: #666; color: #666;
} }
/* 响应式设计 */
@media (max-width: 768px) {
.production-issue-pda {
padding: 5px;
}
.function-card {
padding: 15px;
}
.function-icon {
font-size: 36px;
}
.input-with-scan {
flex-direction: column;
}
.material-item {
flex-direction: column;
align-items: flex-start;
gap: 10px;
}
.material-status {
align-self: flex-end;
}
}
</style> </style>

549
src/views/modules/production-issue/productionIssuePda.vue

@ -2,13 +2,13 @@
<div> <div>
<div class="pda-container"> <div class="pda-container">
<div class="status-bar"> <div class="status-bar">
<div class="goBack" @click="goBack"><i class="el-icon-arrow-left"></i>上一页</div>
<div class="goBack" @click="handleBack"><i class="el-icon-arrow-left"></i>上一页</div>
<div class="goBack">{{ functionTitle }}</div> <div class="goBack">{{ functionTitle }}</div>
<div class="network" style="color: #fff" @click="$router.push({ path: '/' })">🏠首页</div> <div class="network" style="color: #fff" @click="$router.push({ path: '/' })">🏠首页</div>
</div> </div>
<div style="overflow-y: auto"> <div style="overflow-y: auto">
<!-- 功能选择 --> <!-- 功能选择 -->
<div class="function-selector" v-if="!selectedFunction">
<div class="function-selector" v-if="processFlag === 1">
<div class="function-card" @click="selectFunction('direct')"> <div class="function-card" @click="selectFunction('direct')">
<div class="function-icon">📦</div> <div class="function-icon">📦</div>
<div class="function-title">直接发料</div> <div class="function-title">直接发料</div>
@ -29,17 +29,14 @@
</div> </div>
<!-- 直接发料 --> <!-- 直接发料 -->
<div class="direct-issue" v-if="selectedFunction === 'direct'">
<div class="direct-issue" v-if="processFlag === 2 && selectedFunction === 'direct'">
<!-- 工单输入 --> <!-- 工单输入 -->
<div class="input-section" v-if="!workOrderMaterials.length">
<div class="input-section">
<div class="input-group"> <div class="input-group">
<label>工单号</label> <label>工单号</label>
<div class="input-with-scan"> <div class="input-with-scan">
<input
v-model="directIssueForm.workOrderNo"
placeholder="请输入或扫描工单号"
@keyup.enter="loadWorkOrderMaterials"
/>
<input v-model="directIssueForm.workOrderNo" placeholder="请输入或扫描工单号"
@keyup.enter="loadWorkOrderMaterials" />
<button @click="loadWorkOrderMaterials" class="scan-btn">确认</button> <button @click="loadWorkOrderMaterials" class="scan-btn">确认</button>
</div> </div>
</div> </div>
@ -47,17 +44,10 @@
<!-- 物料列表 --> <!-- 物料列表 -->
<div class="materials-section" v-if="workOrderMaterials.length"> <div class="materials-section" v-if="workOrderMaterials.length">
<div class="section-header">
<h3>工单物料 ({{ directIssueForm.workOrderNo }})</h3>
<button @click="resetWorkOrder" class="reset-btn">重新选择</button>
</div>
<div class="material-list"> <div class="material-list">
<div v-for="(material, index) in workOrderMaterials" :key="index"
class="material-item"
<div v-for="(material, index) in workOrderMaterials" :key="index" class="material-item"
:class="{ selected: (selectedMaterial?selectedMaterial.partNo:'') === (material&&material.partNo?material.partNo:'') }" :class="{ selected: (selectedMaterial?selectedMaterial.partNo:'') === (material&&material.partNo?material.partNo:'') }"
@click="selectMaterial(material)"
>
@click="goToScanLabel(material)">
<div class="material-info"> <div class="material-info">
<div class="part-no">{{ material.partNo }}</div> <div class="part-no">{{ material.partNo }}</div>
<div class="part-desc">{{ material.partDesc }}</div> <div class="part-desc">{{ material.partDesc }}</div>
@ -74,85 +64,16 @@
</div> </div>
</div> </div>
</div> </div>
<!-- 扫描标签 -->
<div class="scan-section" v-if="selectedMaterial">
<div class="section-header">
<h3>扫描物料标签</h3>
</div>
<div class="input-group">
<label>物料标签</label>
<div class="input-with-scan">
<input
v-model="scannedLabel"
placeholder="请扫描物料标签"
@keyup.enter="parseMaterialLabel"
/>
<button @click="parseMaterialLabel" class="scan-btn">解析</button>
</div>
</div>
<!-- 标签信息 -->
<div class="label-info" v-if="labelInfo">
<div class="info-row">
<span class="label">物料编码:</span>
<span class="value">{{ labelInfo.partNo }}</span>
</div>
<div class="info-row">
<span class="label">物料描述:</span>
<span class="value">{{ labelInfo.partDesc }}</span>
</div>
<div class="info-row">
<span class="label">批次号:</span>
<span class="value">{{ labelInfo.batchNo }}</span>
</div>
<div class="info-row">
<span class="label">库位:</span>
<span class="value">{{ labelInfo.locationId }}</span>
</div>
<div class="info-row">
<span class="label">可用数量:</span>
<span class="value">{{ labelInfo.availableQty }}</span>
</div>
</div>
<!-- 发料数量 -->
<div class="qty-input" v-if="labelInfo">
<div class="input-group">
<label>发料数量</label>
<input
v-model="issueQty"
type="number"
:max="Math.min(selectedMaterial.remainQty, labelInfo.availableQty)"
placeholder="请输入发料数量"
/>
</div>
<div class="input-group">
<label>备注</label>
<input v-model="directIssueForm.remark" placeholder="可选" />
</div>
<button @click="confirmDirectIssue" class="confirm-btn" :disabled="!issueQty">
确认发料
</button>
</div>
</div>
</div> </div>
<!-- 拣选装托盘 --> <!-- 拣选装托盘 -->
<div class="picking-pallet" v-if="selectedFunction === 'picking'">
<div class="picking-pallet" v-if="processFlag === 2 && selectedFunction === 'picking'">
<!-- 申请单输入 --> <!-- 申请单输入 -->
<div class="input-section" v-if="!currentPallet.palletId"> <div class="input-section" v-if="!currentPallet.palletId">
<div class="input-group"> <div class="input-group">
<label>申请单号</label> <label>申请单号</label>
<div class="input-with-scan"> <div class="input-with-scan">
<input
v-model="palletForm.notifyNo"
placeholder="请输入申请单号"
@keyup.enter="createPallet"
/>
<input v-model="palletForm.notifyNo" placeholder="请输入申请单号" @keyup.enter="createPallet" />
<button @click="createPallet" class="scan-btn">创建托盘</button> <button @click="createPallet" class="scan-btn">创建托盘</button>
</div> </div>
</div> </div>
@ -184,11 +105,7 @@
<div class="input-group"> <div class="input-group">
<label>扫描箱/</label> <label>扫描箱/</label>
<div class="input-with-scan"> <div class="input-with-scan">
<input
v-model="scannedUnit"
placeholder="请扫描处理单元条码"
@keyup.enter="bindUnit"
/>
<input v-model="scannedUnit" placeholder="请扫描处理单元条码" @keyup.enter="bindUnit" />
<button @click="bindUnit" class="scan-btn">绑定</button> <button @click="bindUnit" class="scan-btn">绑定</button>
</div> </div>
</div> </div>
@ -225,17 +142,13 @@
</div> </div>
<!-- 申请单发料 --> <!-- 申请单发料 -->
<div class="request-issue" v-if="selectedFunction === 'request'">
<div class="request-issue" v-if="processFlag === 2 && selectedFunction === 'request'">
<!-- 申请单输入 --> <!-- 申请单输入 -->
<div class="input-section" v-if="!requestMaterials.length">
<div class="input-section">
<div class="input-group"> <div class="input-group">
<label>申请单号</label> <label>申请单号</label>
<div class="input-with-scan"> <div class="input-with-scan">
<input
v-model="requestIssueForm.notifyNo"
placeholder="请输入申请单号"
@keyup.enter="loadRequestMaterials"
/>
<input v-model="requestIssueForm.notifyNo" placeholder="请输入申请单号" @keyup.enter="loadRequestMaterials" />
<button @click="loadRequestMaterials" class="scan-btn">确认</button> <button @click="loadRequestMaterials" class="scan-btn">确认</button>
</div> </div>
</div> </div>
@ -243,54 +156,20 @@
<!-- 申请单物料列表 --> <!-- 申请单物料列表 -->
<div class="materials-section" v-if="requestMaterials.length"> <div class="materials-section" v-if="requestMaterials.length">
<div class="section-header">
<h3>申请单物料 ({{ requestIssueForm.notifyNo }})</h3>
<button @click="resetRequest" class="reset-btn">重新选择</button>
</div>
<div class="material-list"> <div class="material-list">
<div
v-for="material in requestMaterials"
:key="`${material.partNo}-${material.itemNo}`"
class="material-item"
:class="{ selected: selectedRequestMaterial.itemNo === material.itemNo }"
@click="selectRequestMaterial(material)"
>
<div class="material-info">
<div class="part-no">{{ material.partNo }}</div>
<div class="part-desc">{{ material.partDesc }}</div>
<div class="work-order">工单: {{ material.workOrderNo }}</div>
<div class="qty-info">
申请: {{ material.requestQty }} |
已发: {{ material.issuedQty }} |
剩余: {{ material.remainQty }}
</div>
</div>
<div class="material-status">
<span v-if="material.remainQty > 0" class="status-pending">待发料</span>
<span v-else class="status-complete">已完成</span>
</div>
</div>
</div>
</div>
<!-- 扫描标签和发料 --> <!-- 扫描标签和发料 -->
<div class="scan-section" v-if="selectedRequestMaterial">
<!-- <div class="scan-section">
<div class="section-header"> <div class="section-header">
<h3>扫描物料标签</h3> <h3>扫描物料标签</h3>
</div> </div>
<div class="input-group"> <div class="input-group">
<label>物料标签</label>
<div class="input-with-scan"> <div class="input-with-scan">
<input
v-model="scannedLabel"
placeholder="请扫描物料标签"
@keyup.enter="parseMaterialLabel"
/>
<input v-model="scannedLabel" placeholder="请扫描物料标签" @keyup.enter="parseMaterialLabel" />
<button @click="parseMaterialLabel" class="scan-btn">解析</button> <button @click="parseMaterialLabel" class="scan-btn">解析</button>
</div> </div>
</div>
</div> -->
<!-- 标签信息和发料确认 --> <!-- 标签信息和发料确认 -->
<div class="label-info" v-if="labelInfo"> <div class="label-info" v-if="labelInfo">
@ -310,17 +189,17 @@
<div class="qty-input"> <div class="qty-input">
<div class="input-group"> <div class="input-group">
<label>发料数量</label> <label>发料数量</label>
<input
v-model="issueQty"
type="number"
<input v-model="issueQty" type="number"
:max="Math.min(selectedRequestMaterial.remainQty, labelInfo.availableQty)" :max="Math.min(selectedRequestMaterial.remainQty, labelInfo.availableQty)"
placeholder="请输入发料数量"
/>
placeholder="请输入发料数量" />
</div> </div>
<div class="input-group"> <div class="input-group">
<label>备注</label> <label>备注</label>
<input v-model="requestIssueForm.remark" placeholder="可选" />
<div class="input-with-scan">
<textarea v-model="requestIssueForm.remark" placeholder="可选" />
</div>
</div> </div>
<button @click="confirmRequestIssue" class="confirm-btn" :disabled="!issueQty"> <button @click="confirmRequestIssue" class="confirm-btn" :disabled="!issueQty">
@ -329,6 +208,26 @@
</div> </div>
</div> </div>
</div> </div>
<div v-for="material in requestMaterials" :key="`${material.partNo}-${material.itemNo}`"
class="material-item" @click="selectRequestMaterial(material)">
<div class="material-info">
<div class="part-no">{{ material.partNo }}</div>
<div class="part-desc">{{ material.partDesc }}</div>
<div class="work-order">工单: {{ material.workOrderNo }}</div>
<div class="qty-info">
申请: {{ material.requestQty }} |
已发: {{ material.issuedQty }} |
剩余: {{ material.remainQty }}
</div>
</div>
<div class="material-status">
<span v-if="material.remainQty > 0" class="status-pending">待发料</span>
<span v-else class="status-complete">已完成</span>
</div>
</div>
</div>
</div>
</div> </div>
<!-- 加载提示 --> <!-- 加载提示 -->
@ -341,6 +240,35 @@
<div class="message" v-if="message" :class="messageType"> <div class="message" v-if="message" :class="messageType">
{{ message }} {{ message }}
</div> </div>
<!-- 扫描标签页面 -->
<div v-if="processFlag === 3" class="scan-label-page">
<div class="input-section">
<div class="label-info" v-if="scanLabelData.labelInfo">
<div class="info-row"><span class="label">物料编码:</span><span
class="value">{{ scanLabelData.labelInfo.partNo }}</span></div>
<div class="info-row"><span class="label">批次号:</span><span
class="value">{{ scanLabelData.labelInfo.batchNo }}</span></div>
<div class="info-row"><span class="label">可用数量:</span><span
class="value">{{ scanLabelData.labelInfo.availableQty }}</span></div>
</div>
<div class="qty-input" v-if="scanLabelData.labelInfo">
<div class="input-group">
<label>发料数量</label>
<input v-model="scanLabelData.issueQty" type="number" :max="scanLabelData.labelInfo.availableQty"
placeholder="请输入发料数量" />
</div>
<div class="input-group">
<label>备注</label>
<el-input type="textarea" v-model="scanLabelData.remark" placeholder="可选" />
</div>
<button @click="confirmScanLabelIssue" class="confirm-btn" :disabled="!scanLabelData.issueQty">确认发料</button>
</div>
<div class="message" v-if="scanLabelData.message" :class="scanLabelData.messageType">
{{ scanLabelData.message }}</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -356,13 +284,14 @@ import {
createPickingPallet, createPickingPallet,
bindUnitsToPallet, bindUnitsToPallet,
printPalletLabel, printPalletLabel,
getPalletInfo
getPalletInfo,
} from '@/api/production/production-issue' } from '@/api/production/production-issue'
export default { export default {
name: 'ProductionIssuePDA', name: 'ProductionIssuePDA',
data() { data() {
return { return {
processFlag: 1, // 1=, 2=, 3=, 4=
selectedFunction: null, selectedFunction: null,
loading: false, loading: false,
loadingText: '', loadingText: '',
@ -375,7 +304,7 @@ export default {
workOrderNo: '', workOrderNo: '',
operatorName: 'PDA_USER', operatorName: 'PDA_USER',
remark: '', remark: '',
selectedMaterials: []
selectedMaterials: [],
}, },
workOrderMaterials: [], workOrderMaterials: [],
selectedMaterial: { selectedMaterial: {
@ -383,7 +312,7 @@ export default {
partDesc: '', partDesc: '',
requiredQty: 0, requiredQty: 0,
issuedQty: 0, issuedQty: 0,
remainQty: 0
remainQty: 0,
}, },
// //
@ -393,7 +322,7 @@ export default {
workOrderNo: '', workOrderNo: '',
operatorName: 'PDA_USER', operatorName: 'PDA_USER',
remark: '', remark: '',
selectedMaterials: []
selectedMaterials: [],
}, },
requestMaterials: [], requestMaterials: [],
selectedRequestMaterial: null, selectedRequestMaterial: null,
@ -404,7 +333,7 @@ export default {
notifyNo: '', notifyNo: '',
operatorName: 'PDA_USER', operatorName: 'PDA_USER',
printerName: '', printerName: '',
remark: ''
remark: '',
}, },
currentPallet: {}, currentPallet: {},
scannedUnit: '', scannedUnit: '',
@ -412,33 +341,98 @@ export default {
// //
scannedLabel: '', scannedLabel: '',
labelInfo: null, labelInfo: null,
issueQty: null
issueQty: null,
showScanLabel: false,
scanLabelContext: {},
scanLabelData: {},
} }
}, },
computed: { computed: {
functionTitle() { functionTitle() {
if (!this.selectedFunction) return '生产发料';
if (this.selectedFunction === 'direct') return '直接发料';
if (this.selectedFunction === 'picking') return '拣选装托盘';
if (this.selectedFunction === 'request') return '申请单发料';
return '生产发料';
}
if (!this.selectedFunction) return '生产发料'
if (this.selectedFunction === 'direct') return '直接发料'
if (this.selectedFunction === 'picking') return '拣选装托盘'
if (this.selectedFunction === 'request') return '申请单发料'
return '生产发料'
},
}, },
methods: { methods: {
handleBack() {
if (this.processFlag === 3) {
this.processFlag = 2
this.showScanLabel = false
} else if (this.processFlag === 2) {
this.processFlag = 1
this.selectedFunction = null
} else if (this.processFlag === 1) {
this.$router.push('/')
}
},
selectFunction(func) { selectFunction(func) {
this.selectedFunction = func this.selectedFunction = func
this.resetAll() this.resetAll()
this.processFlag = 2
}, },
goBack() {
if (!this.selectedFunction) {
this.$router.push('/')
} else {
this.selectedFunction = null
this.resetAll()
goToScanLabel(material) {
if (material.remainQty <= 0) {
this.showMessage('该物料已发料完成', 'warning')
return
} }
this.scanLabelContext = {
type: 'direct',
workOrderNo: this.directIssueForm.workOrderNo,
partNo: material.partNo,
material,
}
this.scanLabelData = {
scannedLabel: '',
labelInfo: {
partNo: this.partNo,
batchNo: 'BATCH001',
availableQty: 100,
},
issueQty: null,
remark: '',
message: '',
messageType: 'info',
}
this.showScanLabel = true
this.processFlag = 3
},
selectRequestMaterial(material) {
if (material.remainQty <= 0) {
this.showMessage('该物料已发料完成', 'warning')
return
}
this.selectedRequestMaterial = material
this.requestIssueForm.workOrderNo = material.workOrderNo
this.scannedLabel = ''
this.labelInfo = null
this.issueQty = null
this.scanLabelContext = {
type: 'request',
notifyNo: this.requestIssueForm.notifyNo,
partNo: material.partNo,
material,
}
this.scanLabelData = {
scannedLabel: '',
labelInfo: {
partNo: this.partNo,
batchNo: 'BATCH001',
availableQty: 100,
},
issueQty: null,
remark: '',
message: '',
messageType: 'info',
}
this.showScanLabel = true
this.processFlag = 3
},
closeScanLabel() {
this.handleBack()
}, },
resetAll() { resetAll() {
this.workOrderMaterials = [] this.workOrderMaterials = []
this.requestMaterials = [] this.requestMaterials = []
@ -464,7 +458,7 @@ export default {
try { try {
const response = await getWorkOrderMaterials({ const response = await getWorkOrderMaterials({
site: this.directIssueForm.site, site: this.directIssueForm.site,
workOrderNo: this.directIssueForm.workOrderNo
workOrderNo: this.directIssueForm.workOrderNo,
}) })
if (response.data.code === 0) { if (response.data.code === 0) {
@ -482,26 +476,6 @@ export default {
} }
}, },
selectMaterial(material) {
if (material.remainQty <= 0) {
this.showMessage('该物料已发料完成', 'warning')
return
}
this.selectedMaterial = material
this.scannedLabel = ''
this.labelInfo = null
this.issueQty = null
},
resetWorkOrder() {
this.directIssueForm.workOrderNo = ''
this.workOrderMaterials = []
this.selectedMaterial = null
this.scannedLabel = ''
this.labelInfo = null
this.issueQty = null
},
async confirmDirectIssue() { async confirmDirectIssue() {
if (!this.issueQty || this.issueQty <= 0) { if (!this.issueQty || this.issueQty <= 0) {
this.showMessage('请输入有效的发料数量', 'error') this.showMessage('请输入有效的发料数量', 'error')
@ -514,11 +488,13 @@ export default {
try { try {
const issueData = { const issueData = {
...this.directIssueForm, ...this.directIssueForm,
selectedMaterials: [{
selectedMaterials: [
{
...this.selectedMaterial, ...this.selectedMaterial,
issueQty: this.issueQty
}],
scannedLabel: this.scannedLabel
issueQty: this.issueQty,
},
],
scannedLabel: this.scannedLabel,
} }
const response = await directIssue(issueData) const response = await directIssue(issueData)
@ -544,7 +520,7 @@ export default {
// //
async loadRequestMaterials() { async loadRequestMaterials() {
if (!this.requestIssueForm.notifyNo) {
/* if (!this.requestIssueForm.notifyNo) {
this.showMessage('请输入申请单号', 'error') this.showMessage('请输入申请单号', 'error')
return return
} }
@ -555,7 +531,7 @@ export default {
try { try {
const response = await getRequestMaterials({ const response = await getRequestMaterials({
site: this.requestIssueForm.site, site: this.requestIssueForm.site,
notifyNo: this.requestIssueForm.notifyNo
notifyNo: this.requestIssueForm.notifyNo,
}) })
if (response.data.code === 0) { if (response.data.code === 0) {
@ -570,29 +546,31 @@ export default {
this.showMessage('加载申请单物料失败', 'error') this.showMessage('加载申请单物料失败', 'error')
} finally { } finally {
this.loading = false this.loading = false
}
} */
let materials = [
{
partNo: 'PART001',
partDesc: '物料描述1',
workOrderNo: 'WO001',
requestQty: 100,
issuedQty: 50,
remainQty: 50,
itemNo: 'ITEM001',
}, },
selectRequestMaterial(material) {
if (material.remainQty <= 0) {
this.showMessage('该物料已发料完成', 'warning')
return
}
this.selectedRequestMaterial = material
this.requestIssueForm.workOrderNo = material.workOrderNo
this.scannedLabel = ''
this.labelInfo = null
this.issueQty = null
{
partNo: 'PART002',
partDesc: '物料描述2',
workOrderNo: 'WO002',
requestQty: 200,
issuedQty: 100,
remainQty: 100,
itemNo: 'ITEM002',
}, },
]
resetRequest() {
this.requestIssueForm.notifyNo = ''
this.requestIssueForm.workOrderNo = ''
this.requestMaterials = []
this.selectedRequestMaterial = null
this.scannedLabel = ''
this.labelInfo = null
this.issueQty = null
//this.requestMaterials = materials
this.$set(this, 'requestMaterials', materials)
}, },
async confirmRequestIssue() { async confirmRequestIssue() {
@ -607,11 +585,13 @@ export default {
try { try {
const issueData = { const issueData = {
...this.requestIssueForm, ...this.requestIssueForm,
selectedMaterials: [{
selectedMaterials: [
{
...this.selectedRequestMaterial, ...this.selectedRequestMaterial,
issueQty: this.issueQty
}],
scannedLabel: this.scannedLabel
issueQty: this.issueQty,
},
],
scannedLabel: this.scannedLabel,
} }
const response = await requestIssue(issueData) const response = await requestIssue(issueData)
@ -637,7 +617,7 @@ export default {
// //
async createPallet() { async createPallet() {
if (!this.palletForm.notifyNo) {
/* if (!this.palletForm.notifyNo) {
this.showMessage('请输入申请单号', 'error') this.showMessage('请输入申请单号', 'error')
return return
} }
@ -648,7 +628,7 @@ export default {
try { try {
const response = await createPickingPallet({ const response = await createPickingPallet({
...this.palletForm, ...this.palletForm,
palletType: 'PALLET'
palletType: 'PALLET',
}) })
if (response.data.code === 0) { if (response.data.code === 0) {
@ -656,7 +636,7 @@ export default {
palletId: response.data.palletId, palletId: response.data.palletId,
notifyNo: this.palletForm.notifyNo, notifyNo: this.palletForm.notifyNo,
scannedUnits: [], scannedUnits: [],
unitCount: 0
unitCount: 0,
} }
this.showMessage('托盘创建成功: ' + response.data.palletId, 'success') this.showMessage('托盘创建成功: ' + response.data.palletId, 'success')
} else { } else {
@ -666,6 +646,12 @@ export default {
this.showMessage('创建托盘失败', 'error') this.showMessage('创建托盘失败', 'error')
} finally { } finally {
this.loading = false this.loading = false
} */
this.currentPallet = {
palletId: 'qeqweqeqweq',
notifyNo: 'SOIA00000035',
scannedUnits: [],
unitCount: 0,
} }
}, },
@ -688,7 +674,7 @@ export default {
const response = await bindUnitsToPallet({ const response = await bindUnitsToPallet({
site: this.palletForm.site, site: this.palletForm.site,
palletId: this.currentPallet.palletId, palletId: this.currentPallet.palletId,
scannedUnits: [this.scannedUnit]
scannedUnits: [this.scannedUnit],
}) })
if (response.data.code === 0) { if (response.data.code === 0) {
@ -719,7 +705,7 @@ export default {
const response = await printPalletLabel({ const response = await printPalletLabel({
site: this.palletForm.site, site: this.palletForm.site,
palletId: this.currentPallet.palletId, palletId: this.currentPallet.palletId,
printerName: this.palletForm.printerName
printerName: this.palletForm.printerName,
}) })
if (response.data.code === 0) { if (response.data.code === 0) {
@ -736,7 +722,7 @@ export default {
// //
async parseMaterialLabel() { async parseMaterialLabel() {
if (!this.scannedLabel) {
/* if (!this.scannedLabel) {
this.showMessage('请扫描物料标签', 'error') this.showMessage('请扫描物料标签', 'error')
return return
} }
@ -763,7 +749,14 @@ export default {
this.labelInfo = null this.labelInfo = null
} finally { } finally {
this.loading = false this.loading = false
} */
this.labelInfo = {
partNo: this.selectedMaterial.partNo,
batchNo: 'BATCH001',
availableQty: 100,
} }
this.issueQty = null //
this.showMessage('标签解析成功', 'success')
}, },
showMessage(text, type = 'info') { showMessage(text, type = 'info') {
@ -772,8 +765,78 @@ export default {
setTimeout(() => { setTimeout(() => {
this.message = '' this.message = ''
}, 3000) }, 3000)
},
async confirmScanLabelIssue() {
if (!this.scanLabelData.issueQty || this.scanLabelData.issueQty <= 0) {
this.scanLabelData.message = '请输入有效的发料数量'
this.scanLabelData.messageType = 'error'
return
}
this.loading = true
this.scanLabelData.message = ''
try {
if (this.scanLabelContext.type === 'direct') {
//
const issueData = {
...this.directIssueForm,
selectedMaterials: [
{
...this.scanLabelContext.material,
issueQty: this.scanLabelData.issueQty
}
],
scannedLabel: this.scanLabelData.scannedLabel,
remark: this.scanLabelData.remark
} }
const response = await directIssue(issueData)
if (response.data.code === 0) {
this.scanLabelData.message = '发料成功'
this.scanLabelData.messageType = 'success'
await this.loadWorkOrderMaterials()
setTimeout(() => {
this.showScanLabel = false
this.processFlag = 2
}, 1000)
} else {
this.scanLabelData.message = response.data.msg || '发料失败'
this.scanLabelData.messageType = 'error'
}
} else if (this.scanLabelContext.type === 'request') {
//
const issueData = {
...this.requestIssueForm,
selectedMaterials: [
{
...this.scanLabelContext.material,
issueQty: this.scanLabelData.issueQty
} }
],
scannedLabel: this.scanLabelData.scannedLabel,
remark: this.scanLabelData.remark
}
const response = await requestIssue(issueData)
if (response.data.code === 0) {
this.scanLabelData.message = '发料成功'
this.scanLabelData.messageType = 'success'
await this.loadRequestMaterials()
setTimeout(() => {
this.showScanLabel = false
this.processFlag = 2
}, 1000)
} else {
this.scanLabelData.message = response.data.msg || '发料失败'
this.scanLabelData.messageType = 'error'
}
}
} catch (error) {
this.scanLabelData.message = '发料异常'
this.scanLabelData.messageType = 'error'
} finally {
this.loading = false
}
},
},
} }
</script> </script>
@ -797,7 +860,7 @@ export default {
background: white; background: white;
border-radius: 8px; border-radius: 8px;
padding: 20px; padding: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
cursor: pointer; cursor: pointer;
transition: all 0.3s; transition: all 0.3s;
text-align: center; text-align: center;
@ -805,7 +868,7 @@ export default {
.function-card:hover { .function-card:hover {
transform: translateY(-2px); transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
} }
.function-icon { .function-icon {
@ -826,12 +889,16 @@ export default {
} }
/* 输入区域 */ /* 输入区域 */
.input-section, .materials-section, .scan-section, .pallet-info, .print-section {
.input-section,
.materials-section,
.scan-section,
.pallet-info,
.print-section {
background: white; background: white;
border-radius: 8px; border-radius: 8px;
padding: 15px; padding: 15px;
margin-bottom: 15px; margin-bottom: 15px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
} }
.section-header { .section-header {
@ -843,7 +910,8 @@ export default {
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
} }
.section-header h3, .section-header h4 {
.section-header h3,
.section-header h4 {
margin: 0; margin: 0;
color: #333; color: #333;
} }
@ -882,7 +950,9 @@ export default {
font-size: 16px; font-size: 16px;
} }
.scan-btn, .confirm-btn, .print-btn {
.scan-btn,
.confirm-btn,
.print-btn {
background: #17b3a3; background: #17b3a3;
color: white; color: white;
border: none; border: none;
@ -893,11 +963,14 @@ export default {
white-space: nowrap; white-space: nowrap;
} }
.scan-btn:hover, .confirm-btn:hover, .print-btn:hover {
.scan-btn:hover,
.confirm-btn:hover,
.print-btn:hover {
background: #13998c; background: #13998c;
} }
.confirm-btn:disabled, .print-btn:disabled {
.confirm-btn:disabled,
.print-btn:disabled {
background: #6c757d; background: #6c757d;
cursor: not-allowed; cursor: not-allowed;
} }
@ -979,7 +1052,8 @@ export default {
} }
/* 标签信息 */ /* 标签信息 */
.label-info, .info-card {
.label-info,
.info-card {
background: #f8f9fa; background: #f8f9fa;
border-radius: 6px; border-radius: 6px;
padding: 15px; padding: 15px;
@ -1013,7 +1087,7 @@ export default {
margin-top: 15px; margin-top: 15px;
} }
.qty-input input[type="number"] {
.qty-input input[type='number'] {
width: 100%; width: 100%;
padding: 10px; padding: 10px;
border: 1px solid #ddd; border: 1px solid #ddd;
@ -1052,7 +1126,7 @@ export default {
top: 50%; top: 50%;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
background: rgba(0,0,0,0.8);
background: rgba(0, 0, 0, 0.8);
color: white; color: white;
padding: 20px; padding: 20px;
border-radius: 8px; border-radius: 8px;
@ -1071,8 +1145,12 @@ export default {
} }
@keyframes spin { @keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
} }
.loading-text { .loading-text {
@ -1144,4 +1222,7 @@ export default {
align-self: flex-end; align-self: flex-end;
} }
} }
.confirm-btn {
width: 100%;
}
</style> </style>
Loading…
Cancel
Save