10 changed files with 2149 additions and 2 deletions
-
19src/api/customerIssue/customer-issue.js
-
6src/router/index.js
-
11src/views/main.vue
-
170src/views/modules/customerIssue/customerIssue.vue
-
659src/views/modules/customerIssue/customerIssuePDA.vue
-
1078src/views/modules/customerIssue/customerIssuePDAIssueList.vue
-
163src/views/modules/customerIssue/customerIssuePDAList.vue
-
3src/views/modules/production-return/productionReturnPDA.vue
-
26src/views/modules/production-return/productionReturnPDAIssueList.vue
-
16src/views/modules/production-return/productionReturnPDAList.vue
@ -0,0 +1,19 @@ |
|||||
|
import { createAPI } from "@/utils/httpRequest.js"; |
||||
|
|
||||
|
|
||||
|
export const getCustomerIssueNotifyHeaderInfo = data => createAPI(`/pda/customerIssue/getCustomerIssueNotifyHeaderInfo`,'post',data) |
||||
|
|
||||
|
// 获取客户发料申请单物料清单
|
||||
|
export const getCustomerIssueNotifyHeaderOrderMaterialList = data => createAPI(`/pda/customerIssue/getCustomerIssueNotifyHeaderOrderMaterialList`,'post',data) |
||||
|
|
||||
|
// 获取客户发料物料记录
|
||||
|
export const getCustomerIssueMatericalForShopOrder = data => createAPI(`/pda/customerIssue/getCustomerIssueMatericalForShopOrder`,'post',data) |
||||
|
|
||||
|
// 扫描客户发料物料标签
|
||||
|
export const scanCustomerIssueMaterialLabel = data => createAPI(`/pda/customerIssue/scanCustomerIssueMaterialLabel`,'post',data) |
||||
|
|
||||
|
// 客户发料确认
|
||||
|
export const customerIssueConfirm = data => createAPI(`/pda/customerIssue/customerIssueConfirm`,'post',data) |
||||
|
|
||||
|
// 获取库存物料信息
|
||||
|
export const getInventoryPart = data => createAPI(`/pda/customerIssue/getInventoryPart`,'post',data) |
||||
@ -0,0 +1,170 @@ |
|||||
|
<template> |
||||
|
<div class="pda-container"> |
||||
|
<div class="header-bar"> |
||||
|
<div class="header-left" @click="$router.back()"> |
||||
|
<i class="el-icon-arrow-left"></i> |
||||
|
<span>客户发料</span> |
||||
|
</div> |
||||
|
<div class="header-right" @click="$router.push({ path: '/' })">首页</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 功能菜单 --> |
||||
|
<div class="menu-grid"> |
||||
|
<div |
||||
|
class="menu-item" |
||||
|
v-for="(btn, index) in buttons" |
||||
|
:key="index" |
||||
|
:class="{ 'disabled': btn.disabled }" |
||||
|
@click="handleButtonClick(btn)" |
||||
|
> |
||||
|
<div class="menu-icon" :class="btn.iconClass"> |
||||
|
<van-icon :name="btn.icon" size="24" /> |
||||
|
</div> |
||||
|
<div class="menu-text">{{ btn.label }}</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
buttons: [ |
||||
|
/* { icon: 'scan', label: '直接发料', iconClass: 'direct', to: 'customerIssuePicking', disabled: true }, |
||||
|
{ icon: 'records', label: '申请单发料', iconClass: 'request', to: 'customerIssuePDA', disabled: false }, |
||||
|
{ icon: 'logistics', label: '移库发料', iconClass: 'move', to: 'customerIssuePicking', disabled: true }, |
||||
|
{ icon: 'revoke', label: '发料撤销', iconClass: 'cancel', to: 'customerIssuePicking', disabled: true }, */ |
||||
|
{ icon: 'records', label: '申请单发料', iconClass: 'request', to: 'customerIssuePDA', disabled: false }, |
||||
|
] |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
handleButtonClick(btn) { |
||||
|
if (btn.disabled) { |
||||
|
this.$message.warning('正在开发中,敬请期待...'); |
||||
|
} else { |
||||
|
this.$router.push(btn.to); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
:root { |
||||
|
--columns: 3; |
||||
|
--button-size: calc(100vw / var(--columns) - 20px); |
||||
|
} |
||||
|
|
||||
|
/* 头部栏 */ |
||||
|
.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; |
||||
|
font-size: 16px; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
|
||||
|
.header-left i { |
||||
|
margin-right: 8px; |
||||
|
font-size: 18px; |
||||
|
} |
||||
|
|
||||
|
.header-right { |
||||
|
cursor: pointer; |
||||
|
font-size: 16px; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
|
||||
|
.menu-grid { |
||||
|
display: grid; |
||||
|
grid-template-columns: repeat(2, 1fr); |
||||
|
gap: 15px; |
||||
|
padding: 20px; |
||||
|
justify-content: center; |
||||
|
align-content: center; |
||||
|
width: 100%; |
||||
|
} |
||||
|
|
||||
|
.menu-item { |
||||
|
background: white; |
||||
|
border-radius: 12px; |
||||
|
padding: 12px 6px; |
||||
|
text-align: center; |
||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
||||
|
transition: transform 0.2s; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
.menu-item:active { |
||||
|
transform: scale(0.95); |
||||
|
} |
||||
|
|
||||
|
.menu-item.disabled { |
||||
|
opacity: 0.6; |
||||
|
position: relative; |
||||
|
} |
||||
|
|
||||
|
.menu-item.disabled::after { |
||||
|
content: '开发中'; |
||||
|
position: absolute; |
||||
|
top: 8px; |
||||
|
right: 8px; |
||||
|
background: #ff9500; |
||||
|
color: white; |
||||
|
font-size: 8px; |
||||
|
padding: 2px 4px; |
||||
|
border-radius: 8px; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
|
||||
|
.menu-icon { |
||||
|
width: 38px; |
||||
|
height: 38px; |
||||
|
border-radius: 50%; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
margin: 0 auto 6px; |
||||
|
color: white; |
||||
|
} |
||||
|
|
||||
|
.menu-icon.direct { |
||||
|
background: linear-gradient(135deg, #17b3a3 0%, #1dc5ef 100%); |
||||
|
} |
||||
|
|
||||
|
.menu-icon.request { |
||||
|
background: linear-gradient(135deg, #17b3a3 0%, #1dc5ef 100%); |
||||
|
} |
||||
|
|
||||
|
.menu-icon.move { |
||||
|
background: linear-gradient(135deg, #17b3a3 0%, #1dc5ef 100%); |
||||
|
} |
||||
|
|
||||
|
.menu-icon.cancel { |
||||
|
background: linear-gradient(135deg, #17b3a3 0%, #1dc5ef 100%); |
||||
|
} |
||||
|
|
||||
|
.menu-text { |
||||
|
font-size: 10px; |
||||
|
color: #333; |
||||
|
font-weight: bold; |
||||
|
white-space: nowrap; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
margin-top: 2px; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,659 @@ |
|||||
|
<template> |
||||
|
<div class="pda-container"> |
||||
|
<!-- 头部栏 --> |
||||
|
<div class="header-bar"> |
||||
|
<div class="header-left" @click="goBack"> |
||||
|
<i class="el-icon-arrow-left"></i> |
||||
|
<span>{{ functionTitle }}</span> |
||||
|
</div> |
||||
|
<div class="header-right" @click="$router.push({ path: '/' })">首页</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 申请单输入 --> |
||||
|
<div class="search-container"> |
||||
|
<el-input clearable v-model="requestIssueForm.requestNo" placeholder="请输入客户单号" prefix-icon="el-icon-search" |
||||
|
@keyup.enter.native="loadIssueRequestMaterials" ref="requestNoInput" /> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 申请单物料列表 --> |
||||
|
<div class="work-order-list" v-if="issueRequestMaterials.length > 0 "> |
||||
|
<div v-for="material in displayIssueRequestMaterials" :key="`${material.partNo}-${material.itemNo}`" |
||||
|
:class="['work-order-card', { selected: selectedRequestMaterial && isSameRequestMaterial(selectedRequestMaterial, material) }]" @click="selectRequestMaterial(material)"> |
||||
|
<div class="card-title"> |
||||
|
<span class="title-label">申请单号:{{ material.notifyNo }} </span> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 工单号单独一行 --> |
||||
|
<div class="part-desc-row"> |
||||
|
<span class="desc-text">客户订单号:{{ material.soorderNo }}</span> |
||||
|
</div> |
||||
|
|
||||
|
<div class="card-details"> |
||||
|
<div class="detail-item"> |
||||
|
<div class="detail-label">申请数量</div> |
||||
|
<div class="detail-value">{{ material.unissureQty }}</div> |
||||
|
</div> |
||||
|
<div class="detail-item"> |
||||
|
<div class="detail-label">状态</div> |
||||
|
<div class="detail-value">待发料</div> |
||||
|
</div> |
||||
|
<div class="detail-item"> |
||||
|
<div class="detail-label">单位</div> |
||||
|
<div class="detail-value">{{ material.uom || "个" }}</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!-- 材料列表(新增,仿 directIssue.vue) --> |
||||
|
<div |
||||
|
class="content-area" |
||||
|
v-if="selectedWorkOrder && materialList.length > 0" |
||||
|
> |
||||
|
<div |
||||
|
v-for="(material, index) in materialList" |
||||
|
:key="index" |
||||
|
class="material-card" |
||||
|
@click="openIssueDetail(material)" |
||||
|
> |
||||
|
<div class="card-title"> |
||||
|
<span class="title-label" |
||||
|
>物料编码:{{ material.componentPartNo }} 行号:{{ |
||||
|
material.bomItemNo |
||||
|
}}</span |
||||
|
> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 物料描述单独一行 --> |
||||
|
<div class="part-desc-row"> |
||||
|
<span class="desc-text">{{ material.componentPartDesc }}</span> |
||||
|
</div> |
||||
|
|
||||
|
<div class="card-details"> |
||||
|
<div class="detail-item"> |
||||
|
<div class="detail-label">需求数量</div> |
||||
|
<div class="detail-value">{{ material.qtyToIssue }}</div> |
||||
|
</div> |
||||
|
<div class="detail-item"> |
||||
|
<div class="detail-label">已发数量</div> |
||||
|
<div class="detail-value">{{ material.qtyIssued || 0 }}</div> |
||||
|
</div> |
||||
|
<div class="detail-item"> |
||||
|
<div class="detail-label">单位</div> |
||||
|
<div class="detail-value">{{ material.uom || "个" }}</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 空状态 --> |
||||
|
<div |
||||
|
v-if="selectedWorkOrder && materialList.length === 0" |
||||
|
class="empty-state" |
||||
|
> |
||||
|
<i class="el-icon-box"></i> |
||||
|
<p>该申请单暂无材料清单</p> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 加载状态 --> |
||||
|
<div v-if="loading" class="loading-state"> |
||||
|
<i class="el-icon-loading"></i> |
||||
|
<p>加载中...</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { |
||||
|
getCustomerIssueNotifyHeaderInfo, |
||||
|
getCustomerIssueNotifyHeaderOrderMaterialList, |
||||
|
} from '@/api/customerIssue/customer-issue' |
||||
|
import { getWorkOrderMaterials } from '@/api/production/production-issue' |
||||
|
|
||||
|
export default { |
||||
|
name: 'customerIssuePDA', |
||||
|
data() { |
||||
|
return { |
||||
|
loading: false, |
||||
|
loadingText: '', |
||||
|
message: '', |
||||
|
messageType: 'info', |
||||
|
|
||||
|
// 基于申请单发料 |
||||
|
requestIssueForm: { |
||||
|
site: localStorage.getItem('site'), |
||||
|
requestNo: '', |
||||
|
operatorName: 'PDA_USER', |
||||
|
issueReason: '', |
||||
|
targetLocation: '', |
||||
|
remark: '', |
||||
|
createLabel: false, |
||||
|
printerName: '', |
||||
|
}, |
||||
|
issueRequestMaterials: [], |
||||
|
selectedRequestMaterial: null, |
||||
|
selectedWorkOrder:'', |
||||
|
materialList: [], // 新增:材料清单 |
||||
|
showOnlySelected: false, |
||||
|
} |
||||
|
}, |
||||
|
computed: { |
||||
|
functionTitle() { |
||||
|
return '客户单发料' |
||||
|
}, |
||||
|
displayIssueRequestMaterials() { |
||||
|
if (this.showOnlySelected && this.selectedRequestMaterial) { |
||||
|
return [this.selectedRequestMaterial] |
||||
|
} |
||||
|
return this.issueRequestMaterials |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
goBack() { |
||||
|
this.$router.back() |
||||
|
}, |
||||
|
|
||||
|
goBackToMaterials() { |
||||
|
this.selectedRequestMaterial = null |
||||
|
}, |
||||
|
|
||||
|
resetAll() { |
||||
|
this.issueRequestMaterials = [] |
||||
|
this.selectedRequestMaterial = null |
||||
|
this.message = '' |
||||
|
}, |
||||
|
|
||||
|
// 基于申请单发料相关方法 |
||||
|
async loadIssueRequestMaterials() { |
||||
|
if (!this.requestIssueForm.requestNo) { |
||||
|
this.showMessage('请输入发料申请单号', 'error') |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
this.loading = true |
||||
|
this.loadingText = '加载申请单物料...' |
||||
|
this.issueRequestMaterials = [] |
||||
|
this.materialList = [] |
||||
|
this.selectedRequestMaterial = null |
||||
|
this.showOnlySelected = false |
||||
|
|
||||
|
getCustomerIssueNotifyHeaderInfo({ |
||||
|
site: localStorage.getItem('site'), |
||||
|
notifyNo: this.requestIssueForm.requestNo, |
||||
|
}).then(({ data }) => { |
||||
|
if (data.code === 0) { |
||||
|
console.log(data) |
||||
|
|
||||
|
this.issueRequestMaterials = data.data || [] |
||||
|
if (this.issueRequestMaterials.length === 0) { |
||||
|
this.$message.warning('查询申请单不存在') |
||||
|
} |
||||
|
} else { |
||||
|
this.$message.error(data.msg, 'error') |
||||
|
} |
||||
|
}) |
||||
|
.finally(() => { |
||||
|
this.loading = false |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
isSameRequestMaterial(a, b) { |
||||
|
if (!a || !b) return false |
||||
|
return ( |
||||
|
a.notifyNo === b.notifyNo && |
||||
|
a.itemNo === b.itemNo && |
||||
|
a.soorderNo === b.soorderNo |
||||
|
) |
||||
|
}, |
||||
|
selectRequestMaterial(material) { |
||||
|
if ( |
||||
|
this.showOnlySelected && |
||||
|
this.selectedRequestMaterial && |
||||
|
this.isSameRequestMaterial(this.selectedRequestMaterial, material) |
||||
|
) { |
||||
|
// 再次点击同一条,恢复显示所有主数据 |
||||
|
this.selectedRequestMaterial = null |
||||
|
this.selectedWorkOrder = '' |
||||
|
this.materialList = [] |
||||
|
this.showOnlySelected = false |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
// 选择并仅显示当前申请单物料 |
||||
|
this.selectedRequestMaterial = material |
||||
|
this.selectedWorkOrder = material.notifyNo |
||||
|
this.showOnlySelected = true |
||||
|
this.getCustomerIssueNotifyHeaderOrderMaterialList(material) |
||||
|
}, |
||||
|
getCustomerIssueNotifyHeaderOrderMaterialList(material){ |
||||
|
let params = { |
||||
|
site: localStorage.getItem('site'), |
||||
|
notifyNo: material.notifyNo, |
||||
|
itemNo: material.itemNo, |
||||
|
soorderNo: material.soorderNo, |
||||
|
}; |
||||
|
getCustomerIssueNotifyHeaderOrderMaterialList(params).then(({ data }) => { |
||||
|
if (data.code === 0) { |
||||
|
console.log(data) |
||||
|
this.materialList = data.data || [] |
||||
|
if (this.materialList.length === 0) { |
||||
|
this.$message.warning('该申请单行号暂无材料清单') |
||||
|
} |
||||
|
} else { |
||||
|
this.$message.error(data.msg, 'error') |
||||
|
} |
||||
|
}).catch((error) => { |
||||
|
this.$message.error('获取材料清单失败: ' + error.message, 'error') |
||||
|
}); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
|
||||
|
// 打开材料列表页面(仿照 productionReturnPicking.vue 的 openIssueList) |
||||
|
openIssueDetail(material) { |
||||
|
this.$router.push({ |
||||
|
name: 'customerIssuePDAList', |
||||
|
query: { |
||||
|
notifyNo: this.selectedRequestMaterial.notifyNo, // 申请单号 |
||||
|
itemNo: this.selectedRequestMaterial.itemNo, // 申请单行号 |
||||
|
workOrderNo: this.selectedRequestMaterial.soorderNo, // 客户订单号 |
||||
|
partNo: material.componentPartNo, // 物料编码 |
||||
|
unissureQty: material.qtyToIssue, // 需求数量 |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
resetRequest() { |
||||
|
this.requestIssueForm.requestNo = '' |
||||
|
this.issueRequestMaterials = [] |
||||
|
this.selectedRequestMaterial = null |
||||
|
}, |
||||
|
|
||||
|
showMessage(text, type = 'info') { |
||||
|
this.message = text |
||||
|
this.messageType = type |
||||
|
setTimeout(() => { |
||||
|
this.message = '' |
||||
|
}, 3000) |
||||
|
}, |
||||
|
}, |
||||
|
created () { |
||||
|
this.resetRequest() |
||||
|
}, |
||||
|
mounted() { |
||||
|
// 聚焦申请单号输入框 |
||||
|
this.$nextTick(() => { |
||||
|
if (this.$refs.requestNoInput) { |
||||
|
this.$refs.requestNoInput.focus() |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.pda-container { |
||||
|
width: 100vw; |
||||
|
height: 100vh; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
background: #f5f5f5; |
||||
|
} |
||||
|
|
||||
|
/* 头部栏 */ |
||||
|
.header-bar { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
padding: 8px 16px; |
||||
|
background: #17b3a3; |
||||
|
color: white; |
||||
|
height: 40px; |
||||
|
min-height: 40px; |
||||
|
} |
||||
|
|
||||
|
.header-left { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
cursor: pointer; |
||||
|
font-size: 16px; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
|
||||
|
.header-left i { |
||||
|
margin-right: 8px; |
||||
|
font-size: 18px; |
||||
|
} |
||||
|
|
||||
|
.header-right { |
||||
|
cursor: pointer; |
||||
|
font-size: 16px; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
|
||||
|
/* 搜索容器 */ |
||||
|
.search-container { |
||||
|
padding: 12px 16px; |
||||
|
background: white; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 12px; |
||||
|
} |
||||
|
|
||||
|
.search-container .el-input { |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
/* 工单列表 */ |
||||
|
.work-order-list { |
||||
|
overflow-y: auto; |
||||
|
padding: 12px 16px; |
||||
|
} |
||||
|
|
||||
|
/* 工单卡片 */ |
||||
|
.work-order-card { |
||||
|
background: white; |
||||
|
border-radius: 8px; |
||||
|
margin-bottom: 12px; |
||||
|
padding: 16px; |
||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
||||
|
cursor: pointer; |
||||
|
transition: all 0.2s ease; |
||||
|
border: 2px solid transparent; |
||||
|
} |
||||
|
|
||||
|
.work-order-card:hover { |
||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); |
||||
|
transform: translateY(-1px); |
||||
|
} |
||||
|
|
||||
|
.work-order-card.selected { |
||||
|
border-color: #17b3a3; |
||||
|
background: #f0fffe; |
||||
|
} |
||||
|
|
||||
|
.work-order-card:active { |
||||
|
transform: translateY(0); |
||||
|
} |
||||
|
|
||||
|
/* 内容区域 */ |
||||
|
.content-area { |
||||
|
flex: 1; |
||||
|
overflow-y: auto; |
||||
|
padding: 12px 16px; |
||||
|
} |
||||
|
|
||||
|
/* 材料卡片 */ |
||||
|
.material-card { |
||||
|
background: white; |
||||
|
border-radius: 8px; |
||||
|
margin-bottom: 12px; |
||||
|
padding: 16px; |
||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
||||
|
cursor: pointer; |
||||
|
transition: all 0.2s ease; |
||||
|
border: 2px solid transparent; |
||||
|
} |
||||
|
|
||||
|
.material-card:hover { |
||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); |
||||
|
transform: translateY(-1px); |
||||
|
} |
||||
|
|
||||
|
.material-card.selected { |
||||
|
border-color: #17b3a3; |
||||
|
background: #f0fffe; |
||||
|
} |
||||
|
|
||||
|
.material-card:active { |
||||
|
transform: translateY(0); |
||||
|
} |
||||
|
|
||||
|
/* 卡片标题 */ |
||||
|
.card-title { |
||||
|
margin-bottom: 12px; |
||||
|
} |
||||
|
|
||||
|
.title-label { |
||||
|
font-size: 12px; |
||||
|
color: #666; |
||||
|
display: block; |
||||
|
margin-bottom: 4px; |
||||
|
} |
||||
|
|
||||
|
.title-value { |
||||
|
font-size: 16px; |
||||
|
font-weight: bold; |
||||
|
color: #333; |
||||
|
margin-left: 16px; |
||||
|
} |
||||
|
|
||||
|
/* 物料描述行 */ |
||||
|
.part-desc-row { |
||||
|
margin-bottom: 12px; |
||||
|
padding: 0 4px; |
||||
|
} |
||||
|
|
||||
|
.desc-text { |
||||
|
font-size: 12px; |
||||
|
color: #666; |
||||
|
line-height: 1.3; |
||||
|
word-break: break-all; |
||||
|
} |
||||
|
|
||||
|
/* 卡片详情 */ |
||||
|
.card-details { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: flex-start; |
||||
|
gap: 4px; |
||||
|
} |
||||
|
|
||||
|
.detail-item { |
||||
|
flex: 1; |
||||
|
text-align: center; |
||||
|
min-width: 50px; |
||||
|
max-width: 70px; |
||||
|
} |
||||
|
|
||||
|
.detail-label { |
||||
|
font-size: 11px; |
||||
|
color: #666; |
||||
|
margin-bottom: 4px; |
||||
|
line-height: 1.2; |
||||
|
margin-left: -12px; |
||||
|
} |
||||
|
|
||||
|
.detail-value { |
||||
|
font-size: 13px; |
||||
|
color: #333; |
||||
|
line-height: 1.2; |
||||
|
margin-left: -12px; |
||||
|
} |
||||
|
|
||||
|
/* 区域头部 */ |
||||
|
.section-header { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
margin-bottom: 12px; |
||||
|
padding: 12px 16px; |
||||
|
background: white; |
||||
|
border-radius: 8px; |
||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
|
||||
|
.section-header span { |
||||
|
font-size: 14px; |
||||
|
font-weight: 500; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.reset-btn { |
||||
|
background: #17b3a3; |
||||
|
color: white; |
||||
|
border: none; |
||||
|
padding: 6px 12px; |
||||
|
border-radius: 4px; |
||||
|
cursor: pointer; |
||||
|
font-size: 12px; |
||||
|
} |
||||
|
|
||||
|
.reset-btn:hover { |
||||
|
background: #13998c; |
||||
|
} |
||||
|
|
||||
|
/* 输入组 */ |
||||
|
.input-group { |
||||
|
margin-bottom: 12px; |
||||
|
} |
||||
|
|
||||
|
.input-with-scan { |
||||
|
display: flex; |
||||
|
gap: 8px; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.input-with-scan .el-input { |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
/* 复选框组 */ |
||||
|
.checkbox-group { |
||||
|
margin-bottom: 12px; |
||||
|
} |
||||
|
|
||||
|
/* 确认区域 */ |
||||
|
.confirm-section { |
||||
|
padding: 16px; |
||||
|
background: white; |
||||
|
border-radius: 8px; |
||||
|
margin-top: 12px; |
||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
|
||||
|
/* 空状态 */ |
||||
|
.empty-state { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
padding: 60px 20px; |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
.empty-state i { |
||||
|
font-size: 48px; |
||||
|
margin-bottom: 16px; |
||||
|
} |
||||
|
|
||||
|
.empty-state p { |
||||
|
font-size: 14px; |
||||
|
margin: 0; |
||||
|
} |
||||
|
|
||||
|
/* 加载状态 */ |
||||
|
.loading-state { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
padding: 60px 20px; |
||||
|
color: #17b3a3; |
||||
|
} |
||||
|
|
||||
|
.loading-state i { |
||||
|
font-size: 24px; |
||||
|
margin-bottom: 12px; |
||||
|
animation: spin 1s linear infinite; |
||||
|
} |
||||
|
|
||||
|
@keyframes spin { |
||||
|
from { |
||||
|
transform: rotate(0deg); |
||||
|
} |
||||
|
to { |
||||
|
transform: rotate(360deg); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.loading-state p { |
||||
|
font-size: 14px; |
||||
|
margin: 0; |
||||
|
} |
||||
|
|
||||
|
/* 消息提示 */ |
||||
|
.message { |
||||
|
position: fixed; |
||||
|
top: 20px; |
||||
|
left: 50%; |
||||
|
transform: translateX(-50%); |
||||
|
padding: 12px 20px; |
||||
|
border-radius: 6px; |
||||
|
font-weight: bold; |
||||
|
z-index: 1001; |
||||
|
max-width: 90%; |
||||
|
text-align: center; |
||||
|
} |
||||
|
|
||||
|
.message.success { |
||||
|
background: #d4edda; |
||||
|
color: #155724; |
||||
|
border: 1px solid #c3e6cb; |
||||
|
} |
||||
|
|
||||
|
.message.error { |
||||
|
background: #f8d7da; |
||||
|
color: #721c24; |
||||
|
border: 1px solid #f5c6cb; |
||||
|
} |
||||
|
|
||||
|
.message.warning { |
||||
|
background: #fff3cd; |
||||
|
color: #856404; |
||||
|
border: 1px solid #ffeaa7; |
||||
|
} |
||||
|
|
||||
|
.message.info { |
||||
|
background: #d1ecf1; |
||||
|
color: #0c5460; |
||||
|
border: 1px solid #bee5eb; |
||||
|
} |
||||
|
|
||||
|
/* 响应式设计 */ |
||||
|
@media (max-width: 360px) { |
||||
|
.header-bar { |
||||
|
padding: 8px 12px; |
||||
|
} |
||||
|
|
||||
|
.search-container { |
||||
|
padding: 8px 12px; |
||||
|
} |
||||
|
|
||||
|
.work-order-list { |
||||
|
padding: 8px 12px; |
||||
|
} |
||||
|
|
||||
|
.work-order-card { |
||||
|
padding: 12px; |
||||
|
} |
||||
|
|
||||
|
.content-area { |
||||
|
padding: 8px 12px; |
||||
|
} |
||||
|
|
||||
|
.material-card { |
||||
|
padding: 12px; |
||||
|
} |
||||
|
|
||||
|
.card-details { |
||||
|
flex-wrap: wrap; |
||||
|
gap: 6px; |
||||
|
} |
||||
|
|
||||
|
.detail-item { |
||||
|
flex: 0 0 48%; |
||||
|
margin-bottom: 6px; |
||||
|
min-width: 50px; |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
1078
src/views/modules/customerIssue/customerIssuePDAIssueList.vue
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,163 @@ |
|||||
|
<template> |
||||
|
<div class="pda-container"> |
||||
|
<!-- 头部栏 --> |
||||
|
<div class="header-bar"> |
||||
|
<div class="header-left" @click="$router.back()"> |
||||
|
<i class="el-icon-arrow-left"></i> |
||||
|
<span>发料 - 领料记录</span> |
||||
|
</div> |
||||
|
<div class="header-right" @click="$router.push({ path: '/' })">首页</div> |
||||
|
</div> |
||||
|
<div class="search-container"> |
||||
|
<div class="card-title"> |
||||
|
<label class="title-label">客户订单号:{{ workOrderNo }}</label> |
||||
|
</div> |
||||
|
<div class="card-title"> |
||||
|
<label class="title-label">物料编码:{{ partNo }}</label> |
||||
|
</div> |
||||
|
<div class="card-title"> |
||||
|
<label class="title-label">发料数量:{{ unissureQty }}</label> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="content-area"> |
||||
|
<div class="work-order-list" v-if="issueList.length > 0"> |
||||
|
<div |
||||
|
v-for="(item, index) in issueList" |
||||
|
:key="index" |
||||
|
class="material-card" |
||||
|
@click="goDetail(item)" |
||||
|
> |
||||
|
<div class="card-title"> |
||||
|
<span class="title-label"> |
||||
|
物料编码:{{ partNo }} 发料号:{{ item.TRANSACTION_ID }} |
||||
|
</span> |
||||
|
</div> |
||||
|
<div class="part-desc-row"> |
||||
|
<span class="desc-text">批次号:{{ item.LOT_BATCH_NO || '-' }}</span> |
||||
|
</div> |
||||
|
<div class="card-details"> |
||||
|
<div class="detail-item"> |
||||
|
<div class="detail-label">发料数量</div> |
||||
|
<div class="detail-value">{{ item.QUANTITY }}</div> |
||||
|
</div> |
||||
|
<div class="detail-item"> |
||||
|
<div class="detail-label">已发数量</div> |
||||
|
<div class="detail-value">{{ item.QTY_ISSUED || 0 }}</div> |
||||
|
</div> |
||||
|
<div class="detail-item"> |
||||
|
<div class="detail-label">单位</div> |
||||
|
<div class="detail-value">{{ item.uom || '个' }}</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div v-if="!loading && issueList.length === 0" class="empty-state"> |
||||
|
<i class="el-icon-box"></i> |
||||
|
<p>暂无发料记录</p> |
||||
|
</div> |
||||
|
|
||||
|
<div v-if="loading" class="loading-state"> |
||||
|
<i class="el-icon-loading"></i> |
||||
|
<p>加载中...</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { getCustomerIssueMatericalForShopOrder } from '@/api/customerIssue/customer-issue'; |
||||
|
import { notify } from 'node-notifier'; |
||||
|
|
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
workOrderNo: '', |
||||
|
partNo: '', |
||||
|
loading: false, |
||||
|
issueList: [], |
||||
|
unissureQty: 0, |
||||
|
itemNo: '', |
||||
|
}; |
||||
|
}, |
||||
|
methods: { |
||||
|
loadIssueList() { |
||||
|
if (!this.workOrderNo || !this.partNo) { |
||||
|
return; |
||||
|
} |
||||
|
this.loading = true; |
||||
|
const params = { |
||||
|
workOrderNo: this.workOrderNo, |
||||
|
site: localStorage.getItem('site'), |
||||
|
partNo: this.partNo, |
||||
|
}; |
||||
|
getCustomerIssueMatericalForShopOrder(params) |
||||
|
.then(({ data }) => { |
||||
|
this.loading = false; |
||||
|
if (data && data.code === 0) { |
||||
|
this.issueList = data.issueForShopOrder || []; |
||||
|
} else { |
||||
|
this.$message.error(data.msg || '获取发料记录失败'); |
||||
|
this.issueList = []; |
||||
|
} |
||||
|
}) |
||||
|
.catch(() => { |
||||
|
this.loading = false; |
||||
|
this.$message.error('获取发料记录失败'); |
||||
|
}); |
||||
|
}, |
||||
|
goDetail(item) { |
||||
|
this.$router.push({ |
||||
|
name: 'customerIssuePDAIssueList', |
||||
|
query: { |
||||
|
workOrderNo: this.workOrderNo, |
||||
|
material:{ |
||||
|
itemNo: this.itemNo, |
||||
|
partNo: this.partNo, |
||||
|
orderType: 'customerOrder', |
||||
|
ifsTransactionID: item.TRANSACTION_ID, |
||||
|
quantity: item.QUANTITY, |
||||
|
batchNo: item.LOT_BATCH_NO, |
||||
|
unissureQty: this.unissureQty, |
||||
|
ifsAccountingID:item.ACCOUNTING_ID, |
||||
|
qtyIssued:item.QTY_ISSUED || 0, |
||||
|
} |
||||
|
}, |
||||
|
}); |
||||
|
}, |
||||
|
}, |
||||
|
mounted() { |
||||
|
this.workOrderNo = this.$route.query.workOrderNo; |
||||
|
this.partNo = this.$route.query.partNo; |
||||
|
this.unissureQty = this.$route.query.unissureQty; |
||||
|
this.itemNo = this.$route.query.itemNo; |
||||
|
this.loadIssueList(); |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.pda-container { width: 100vw; height: 100vh; display: flex; flex-direction: column; background: #f5f5f5; } |
||||
|
.header-bar { display: flex; justify-content: space-between; align-items: center; padding: 8px 16px; background: #17B3A3; color: white; height: 40px; min-height: 40px; } |
||||
|
.header-left { display: flex; align-items: center; cursor: pointer; font-size: 16px; font-weight: 500; } |
||||
|
.header-left i { margin-right: 8px; font-size: 18px; } |
||||
|
.header-right { cursor: pointer; font-size: 16px; font-weight: 500; } |
||||
|
.content-area { flex: 1; overflow-y: auto; } |
||||
|
.work-order-list { overflow-y: auto; padding: 12px 16px; } |
||||
|
.material-card { background: white; border-radius: 8px; margin-bottom: 12px; padding: 16px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); cursor: pointer; transition: all 0.2s ease; border: 2px solid transparent; } |
||||
|
.material-card:hover { box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); transform: translateY(-1px); } |
||||
|
.material-card:active { transform: translateY(0); } |
||||
|
.card-title { margin-bottom: 12px; } |
||||
|
.title-label { font-size: 12px; color: #666; display: block; margin-bottom: 4px; } |
||||
|
.part-desc-row { margin-bottom: 12px; padding: 0 4px; } |
||||
|
.desc-text { font-size: 12px; color: #666; line-height: 1.3; word-break: break-all; } |
||||
|
.card-details { display: flex; justify-content: space-between; align-items: flex-start; gap: 4px; } |
||||
|
.detail-item { flex: 1; text-align: center; min-width: 50px; max-width: 70px; } |
||||
|
.detail-label { font-size: 11px; color: #666; margin-bottom: 4px; line-height: 1.2; margin-left: -12px; } |
||||
|
.detail-value { font-size: 13px; color: #333; line-height: 1.2; margin-left: -12px; } |
||||
|
.empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 60px 20px; color: #999; } |
||||
|
.empty-state i { font-size: 48px; margin-bottom: 16px; } |
||||
|
.loading-state { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 60px 20px; color: #17B3A3; } |
||||
|
.loading-state i { font-size: 24px; margin-bottom: 12px; animation: spin 1s linear infinite; } |
||||
|
@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } |
||||
|
</style> |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue