9 changed files with 529 additions and 8 deletions
-
5src/api/customerIssue/customer-issue.js
-
1src/router/index.js
-
4src/views/main.vue
-
3src/views/modules/customerIssue/customerIssue.vue
-
514src/views/modules/customerIssue/sales-temporary.vue
-
2src/views/modules/production-issue/directIssueDetail.vue
-
2src/views/modules/production-issue/productionPickingDetail.vue
-
2src/views/modules/production-return/productionReturnPDAIssueList.vue
-
4src/views/modules/production-return/productionReturnPickingDetail.vue
@ -0,0 +1,514 @@ |
|||||
|
<template> |
||||
|
<div> |
||||
|
<div class="pda-container"> |
||||
|
<!-- 头部栏 --> |
||||
|
<div class="header-bar"> |
||||
|
<div class="header-left" @click="handleBack"> |
||||
|
<i class="el-icon-arrow-left"></i> |
||||
|
<span>销售临时</span> |
||||
|
</div> |
||||
|
<div class="header-right" @click="$router.push({ path: '/' })"> |
||||
|
首页 |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="table-body" style="max-height: 500px; overflow-y: auto;"> |
||||
|
<div class="main-content form-section"> |
||||
|
<!-- 标签扫描输入框 --> |
||||
|
<div class="input-group"> |
||||
|
<el-input v-model="labelCode" placeholder="请扫描标签编码" class="form-input" clearable inputmode="none" |
||||
|
autocomplete="off" autocorrect="off" spellcheck="false" @keyup.enter.native="handleLabelScan" |
||||
|
ref="labelInput" /> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 标签信息显示 (扫描后显示) --> |
||||
|
<div v-if="labelInfo" class="info-section"> |
||||
|
<div class="info-title"> |
||||
|
<i class="el-icon-document">标签信息</i> |
||||
|
</div> |
||||
|
|
||||
|
<div class="info-row"> |
||||
|
<span class="info-label">标签编码:</span> |
||||
|
<span class="info-value">{{ labelInfo.unitId || '-' }}</span> |
||||
|
</div> |
||||
|
|
||||
|
<div class="info-row"> |
||||
|
<span class="info-label">物料编码:</span> |
||||
|
<span class="info-value">{{ labelInfo.partNo || '-' }}</span> |
||||
|
</div> |
||||
|
|
||||
|
<div class="info-row"> |
||||
|
<span class="info-label">入库数量:</span> |
||||
|
<el-input v-model="editableQty" class="qty-input" type="number" :min="0" placeholder="请输入数量" clearable /> |
||||
|
</div> |
||||
|
|
||||
|
<div class="info-row"> |
||||
|
<span class="info-label">批次号:</span> |
||||
|
<span class="info-value">{{ labelInfo.batchNo || '-' }}</span> |
||||
|
</div> |
||||
|
|
||||
|
<div class="info-row"> |
||||
|
<span class="info-label">仓库:</span> |
||||
|
<span class="info-value">{{ labelInfo.warehouseId || '-' }}</span> |
||||
|
</div> |
||||
|
|
||||
|
<div class="info-row"> |
||||
|
<span class="info-label">库位:</span> |
||||
|
<span class="info-value">{{ labelInfo.locationId || '-' }}</span> |
||||
|
</div> |
||||
|
|
||||
|
<div class="info-row"> |
||||
|
<span class="info-label">WDR:</span> |
||||
|
<span class="info-value">{{ labelInfo.wdr || '-' }}</span> |
||||
|
</div> |
||||
|
|
||||
|
<div class="info-row"> |
||||
|
<span class="info-label">创建时间:</span> |
||||
|
<span class="info-value">{{ formatDate(labelInfo.createdDate) }}</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 底部操作按钮 --> |
||||
|
<div v-if="labelInfo" class="bottom-actions"> |
||||
|
<button class="action-btn primary" @click="handlePrint" :disabled="printLoading || createloading"> |
||||
|
创建打印 |
||||
|
</button> |
||||
|
<button class="action-btn secondary" @click="clearData"> |
||||
|
清空 |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { |
||||
|
queryLabelInfo, |
||||
|
createNewHu, |
||||
|
} from '@/api/customerIssue/customer-issue.js' |
||||
|
import { printLabelCommon } from '@/api/production/production-inbound.js' |
||||
|
|
||||
|
export default { |
||||
|
name: 'SalesTemporary', |
||||
|
|
||||
|
data() { |
||||
|
return { |
||||
|
site: localStorage.getItem('site'), |
||||
|
labelCode: '', |
||||
|
labelInfo: null, |
||||
|
editableQty: '', |
||||
|
loading: false, |
||||
|
printLoading: false, |
||||
|
createloading: false, |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
/** |
||||
|
* 返回上一页 |
||||
|
*/ |
||||
|
handleBack() { |
||||
|
this.$router.back() |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 处理标签扫描 |
||||
|
*/ |
||||
|
handleLabelScan() { |
||||
|
if (!this.labelCode.trim()) { |
||||
|
this.$message.error('请扫描有效的标签编码') |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
this.loading = true |
||||
|
|
||||
|
queryLabelInfo({ |
||||
|
site: this.site, |
||||
|
labelCode: this.labelCode.trim(), |
||||
|
}) |
||||
|
.then(({ data }) => { |
||||
|
this.loading = false |
||||
|
|
||||
|
if (data && data.code === 0) { |
||||
|
this.labelInfo = data.data |
||||
|
this.editableQty = data.data.qty || '0' |
||||
|
this.$message.success('查询成功') |
||||
|
} else { |
||||
|
this.$message.error(data.msg || '标签不存在') |
||||
|
this.labelCode = '' |
||||
|
this.labelInfo = null |
||||
|
this.focusLabelInput() |
||||
|
} |
||||
|
}) |
||||
|
.catch((error) => { |
||||
|
this.loading = false |
||||
|
console.error('查询标签失败:', error) |
||||
|
this.$message.error('查询异常') |
||||
|
this.labelCode = '' |
||||
|
this.labelInfo = null |
||||
|
this.focusLabelInput() |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 清空数据 |
||||
|
*/ |
||||
|
clearData() { |
||||
|
this.labelCode = '' |
||||
|
this.labelInfo = null |
||||
|
this.editableQty = '' |
||||
|
this.focusLabelInput() |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 聚焦标签输入框 |
||||
|
*/ |
||||
|
focusLabelInput() { |
||||
|
this.$nextTick(() => { |
||||
|
if (this.$refs.labelInput) { |
||||
|
this.$refs.labelInput.focus() |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 格式化日期 |
||||
|
*/ |
||||
|
formatDate(date) { |
||||
|
if (!date) return '-' |
||||
|
|
||||
|
const d = new Date(date) |
||||
|
const year = d.getFullYear() |
||||
|
const month = String(d.getMonth() + 1).padStart(2, '0') |
||||
|
const day = String(d.getDate()).padStart(2, '0') |
||||
|
const hours = String(d.getHours()).padStart(2, '0') |
||||
|
const minutes = String(d.getMinutes()).padStart(2, '0') |
||||
|
|
||||
|
return `${year}-${month}-${day} ${hours}:${minutes}` |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 获取状态标签类型 |
||||
|
*/ |
||||
|
getStatusType(inStockFlag) { |
||||
|
return inStockFlag === 'Y' ? 'success' : 'danger' |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 处理打印 |
||||
|
*/ |
||||
|
handlePrint() { |
||||
|
if (!this.labelInfo || !this.labelInfo.unitId) { |
||||
|
this.$message.error('没有可打印的标签信息') |
||||
|
return |
||||
|
} |
||||
|
if(!this.editableQty){ |
||||
|
this.$message.error('请输入数量') |
||||
|
return |
||||
|
} |
||||
|
this.labelInfo.qty = this.editableQty || '0' |
||||
|
let selectedMaterials = [ |
||||
|
{ |
||||
|
...this.labelInfo, |
||||
|
}, |
||||
|
] |
||||
|
console.log('准备创建新HU并打印,标签信息:', selectedMaterials) |
||||
|
let params = { |
||||
|
site: localStorage.getItem('site'), |
||||
|
workOrderNo: this.labelInfo.workOrderNo || '', |
||||
|
WarehouseId: this.labelInfo.warehouseId || '', |
||||
|
selectedMaterials: selectedMaterials, |
||||
|
} |
||||
|
this.createloading = true |
||||
|
createNewHu(params).then(({ data }) => { |
||||
|
if (data && data.code == 0) { |
||||
|
if(data.unitIds.length == 0){ |
||||
|
this.$message.error('创建拆分新HU失败: 未返回有效的HU信息') |
||||
|
return |
||||
|
} |
||||
|
let printLabelType |
||||
|
if ( |
||||
|
this.labelInfo.partNo && |
||||
|
this.labelInfo.partNo.startsWith('80') |
||||
|
) { |
||||
|
printLabelType = '库存成品标签' |
||||
|
} else { |
||||
|
printLabelType = 'BIL标签' |
||||
|
} |
||||
|
// 调用打印方法,传入unitId数组和标签类型 |
||||
|
this.printViaServer(data.unitIds, printLabelType) |
||||
|
}else { |
||||
|
this.$message.error(data.msg || '创建拆分新HU失败') |
||||
|
} |
||||
|
}) |
||||
|
.catch((error) => { |
||||
|
this.$message.error('创建拆分新HU失败:', error.msg) |
||||
|
}).finally(() => { |
||||
|
this.createloading = false |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 通过服务器打印 |
||||
|
* @param {Array} unitIds - HU unitId列表 |
||||
|
* @param {String} printLabelType - 标签类型 |
||||
|
*/ |
||||
|
async printViaServer(unitIds, printLabelType) { |
||||
|
if (!unitIds || unitIds.length === 0) { |
||||
|
console.warn('没有可打印的标签') |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
this.printLoading = true |
||||
|
|
||||
|
try { |
||||
|
const printRequest = { |
||||
|
userId: localStorage.getItem('userName'), |
||||
|
username: localStorage.getItem('userName'), |
||||
|
site: localStorage.getItem('site'), |
||||
|
unitIds: unitIds, |
||||
|
labelType: printLabelType, |
||||
|
} |
||||
|
console.log('打印请求:', printRequest) |
||||
|
|
||||
|
const { data } = await printLabelCommon(printRequest) |
||||
|
|
||||
|
if (data.code === 200 || data.code === 0) { |
||||
|
this.$message.success(`打印任务已发送!`) |
||||
|
this.clearData() |
||||
|
} else { |
||||
|
this.$message.error(data.msg || '打印失败') |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error('服务器打印失败:', error) |
||||
|
this.$message.error(`打印失败: ${error.message || error}`) |
||||
|
} finally { |
||||
|
this.printLoading = false |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
mounted() { |
||||
|
// 页面加载后自动聚焦标签输入框 |
||||
|
this.focusLabelInput() |
||||
|
}, |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
/* PDA容器样式 */ |
||||
|
.pda-container { |
||||
|
width: 100vw; |
||||
|
height: 120vh; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
background: #f5f5f5; |
||||
|
font-family: 'Arial', sans-serif; |
||||
|
} |
||||
|
|
||||
|
/* 头部栏样式 */ |
||||
|
.header-bar { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
padding: 8px 16px; |
||||
|
background: #17b3a3; |
||||
|
color: white; |
||||
|
height: 40px; |
||||
|
min-height: 40px; |
||||
|
max-height: 40px; |
||||
|
} |
||||
|
|
||||
|
.header-left { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
.header-left i { |
||||
|
margin-right: 8px; |
||||
|
font-size: 18px; |
||||
|
} |
||||
|
|
||||
|
.header-left span { |
||||
|
font-size: 16px; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
|
||||
|
.header-right { |
||||
|
cursor: pointer; |
||||
|
font-size: 14px; |
||||
|
padding: 4px 8px; |
||||
|
border-radius: 4px; |
||||
|
} |
||||
|
|
||||
|
/* 主要内容区 */ |
||||
|
.table-body { |
||||
|
flex: 1; |
||||
|
overflow-y: auto; |
||||
|
} |
||||
|
|
||||
|
.main-content { |
||||
|
padding: 16px; |
||||
|
} |
||||
|
|
||||
|
/* 输入组样式 */ |
||||
|
|
||||
|
.input-label { |
||||
|
display: block; |
||||
|
margin-bottom: 8px; |
||||
|
font-size: 14px; |
||||
|
font-weight: 500; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.form-input { |
||||
|
width: 100%; |
||||
|
height: 44px; |
||||
|
} |
||||
|
|
||||
|
/* 信息展示区 */ |
||||
|
.info-section { |
||||
|
background: white; |
||||
|
border-radius: 8px; |
||||
|
padding: 16px; |
||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
|
||||
|
.info-title { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
font-size: 16px; |
||||
|
font-weight: bold; |
||||
|
color: #17b3a3; |
||||
|
margin-bottom: 6px; |
||||
|
padding-bottom: 5px; |
||||
|
border-bottom: 2px solid #17b3a3; |
||||
|
} |
||||
|
|
||||
|
.info-title i { |
||||
|
margin-right: 8px; |
||||
|
font-size: 18px; |
||||
|
} |
||||
|
|
||||
|
/* 数量输入框 */ |
||||
|
.qty-input { |
||||
|
flex: 1; |
||||
|
max-width: 200px; |
||||
|
margin-left: auto; |
||||
|
} |
||||
|
|
||||
|
.qty-input >>> .el-input__inner { |
||||
|
text-align: center; |
||||
|
font-size: 14px; |
||||
|
font-weight: 500; |
||||
|
color: #333; |
||||
|
height: 32px; |
||||
|
line-height: 32px; |
||||
|
} |
||||
|
|
||||
|
.info-row { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: flex-start; |
||||
|
padding: 10px 0; |
||||
|
border-bottom: 1px solid #f0f0f0; |
||||
|
} |
||||
|
|
||||
|
.info-row:last-child { |
||||
|
border-bottom: none; |
||||
|
} |
||||
|
|
||||
|
.info-label { |
||||
|
font-size: 14px; |
||||
|
color: #666; |
||||
|
min-width: 90px; |
||||
|
flex-shrink: 0; |
||||
|
} |
||||
|
|
||||
|
.info-value { |
||||
|
font-size: 14px; |
||||
|
font-weight: 500; |
||||
|
color: #333; |
||||
|
flex: 1; |
||||
|
text-align: right; |
||||
|
word-break: break-all; |
||||
|
} |
||||
|
|
||||
|
/* 底部按钮区 */ |
||||
|
.bottom-actions { |
||||
|
display: flex; |
||||
|
gap: 12px; |
||||
|
padding-top: 16px; |
||||
|
} |
||||
|
|
||||
|
.action-btn { |
||||
|
flex: 1; |
||||
|
padding: 12px 24px; |
||||
|
border: none; |
||||
|
border-radius: 6px; |
||||
|
font-size: 16px; |
||||
|
font-weight: 500; |
||||
|
cursor: pointer; |
||||
|
transition: all 0.2s; |
||||
|
min-height: 44px; |
||||
|
} |
||||
|
|
||||
|
.action-btn.primary { |
||||
|
background: #17b3a3; |
||||
|
color: white; |
||||
|
} |
||||
|
|
||||
|
.action-btn.primary:hover:not(:disabled) { |
||||
|
background: #15a394; |
||||
|
} |
||||
|
|
||||
|
.action-btn.primary:disabled { |
||||
|
background: #ccc; |
||||
|
cursor: not-allowed; |
||||
|
opacity: 0.6; |
||||
|
} |
||||
|
|
||||
|
.action-btn.secondary { |
||||
|
background: #f5f5f5; |
||||
|
color: #333; |
||||
|
border: 1px solid #ddd; |
||||
|
} |
||||
|
|
||||
|
.action-btn.secondary:hover { |
||||
|
background: #e8e8e8; |
||||
|
} |
||||
|
|
||||
|
/* 响应式设计 */ |
||||
|
@media screen and (max-width: 480px) { |
||||
|
.header-bar { |
||||
|
padding: 8px 12px; |
||||
|
} |
||||
|
|
||||
|
.main-content { |
||||
|
padding: 12px; |
||||
|
} |
||||
|
|
||||
|
.info-section { |
||||
|
padding: 2px; |
||||
|
} |
||||
|
|
||||
|
.info-label { |
||||
|
font-size: 13px; |
||||
|
min-width: 80px; |
||||
|
} |
||||
|
|
||||
|
.info-value { |
||||
|
font-size: 13px; |
||||
|
} |
||||
|
|
||||
|
.action-btn { |
||||
|
padding: 10px 16px; |
||||
|
font-size: 14px; |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
|
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue