|
|
|
@ -24,33 +24,91 @@ |
|
|
|
|
|
|
|
<!-- 退货单列表 --> |
|
|
|
<div class="content-area"> |
|
|
|
<div |
|
|
|
v-for="(item, index) in returnList" |
|
|
|
:key="index" |
|
|
|
class="return-card" |
|
|
|
@click="goToReturnPage(item)" |
|
|
|
> |
|
|
|
<div v-for="(item, index) in returnList" :key="index" class="return-group"> |
|
|
|
<!-- 主信息卡片 --> |
|
|
|
<div class="return-card main-card" @click="toggleDetailCards(item)"> |
|
|
|
<div class="card-header"> |
|
|
|
<div class="card-title"> |
|
|
|
<span class="title-label">出库单号</span> |
|
|
|
<span class="title-value">{{ item.returnNo }}</span> |
|
|
|
</div> |
|
|
|
<i |
|
|
|
:class="['expand-icon', 'el-icon-arrow-down', { 'expanded': item.showDetails }]" |
|
|
|
></i> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div class="card-details"> |
|
|
|
<div class="detail-row"> |
|
|
|
<div class="detail-item"> |
|
|
|
<div class="detail-label">客户编码</div> |
|
|
|
<div class="detail-value"> |
|
|
|
<span class="qualified">{{ item.customerId }}</span> |
|
|
|
<span class="detail-label">客户编码:</span> |
|
|
|
<span class="detail-value">{{ item.customerId }}</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div class="detail-item"> |
|
|
|
<div class="detail-label">客户名称</div> |
|
|
|
<div class="detail-value"> |
|
|
|
<span class="qualified">{{ item.customerName }}</span> |
|
|
|
<div class="detail-row"> |
|
|
|
<div class="detail-item full-width"> |
|
|
|
<span class="detail-label">客户名称:</span> |
|
|
|
<span class="detail-value customer-name">{{ item.customerName }}</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<!-- 明细卡片列表 --> |
|
|
|
<div v-if="item.showDetails" class="detail-cards-container"> |
|
|
|
<div v-if="item.detailsLoading" class="detail-loading"> |
|
|
|
<i class="el-icon-loading"></i> |
|
|
|
<p>加载明细中...</p> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div |
|
|
|
v-for="(detail, detailIndex) in item.detailCards" |
|
|
|
:key="detailIndex" |
|
|
|
class="detail-card" |
|
|
|
@click="goToReturnPage(item, detail)" |
|
|
|
> |
|
|
|
<div class="detail-card-header"> |
|
|
|
<div class="part-info"> |
|
|
|
<span class="part-label">物料编码:</span> |
|
|
|
<span class="part-value">{{ detail.partNo }}</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div class="detail-card-body"> |
|
|
|
<div class="part-desc"> |
|
|
|
<span class="desc-label">物料名称:</span> |
|
|
|
<span class="desc-value">{{ detail.partDesc }}</span> |
|
|
|
</div> |
|
|
|
<div class="quantity-info"> |
|
|
|
<div class="qty-item"> |
|
|
|
<span class="qty-label">需求数量:</span> |
|
|
|
<span class="qty-value">{{ detail.totalQty }}</span> |
|
|
|
</div> |
|
|
|
<div class="qty-item"> |
|
|
|
<span class="qty-label">退货数量:</span> |
|
|
|
<span class="qty-value highlight">{{ detail.availableQty }}</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div class="detail-card-footer"> |
|
|
|
<div class="footer-item"> |
|
|
|
<span class="related-label">关联单号:</span> |
|
|
|
<span class="related-value">{{ detail.relatedNo }}</span> |
|
|
|
</div> |
|
|
|
<div class="footer-item"> |
|
|
|
<span class="related-label">关联行号:</span> |
|
|
|
<span class="related-value">{{ detail.relatedLineNo }}</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div v-if="!item.detailsLoading && item.detailCards && item.detailCards.length === 0" class="no-details"> |
|
|
|
<i class="el-icon-document"></i> |
|
|
|
<p>暂无明细数据</p> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
<!-- 空状态 --> |
|
|
|
<div v-if="returnList.length === 0 && !loading" class="empty-state"> |
|
|
|
<i class="el-icon-box"></i> |
|
|
|
@ -67,7 +125,7 @@ |
|
|
|
</template> |
|
|
|
|
|
|
|
<script> |
|
|
|
import { getReturnList } from "@/api/purchase/purchase-return.js"; |
|
|
|
import { getReturnList, getReturnDetailCards } from "@/api/purchase/purchase-return.js"; |
|
|
|
import { getCurrentWarehouse } from '@/utils' |
|
|
|
import moment from 'moment'; |
|
|
|
|
|
|
|
@ -111,7 +169,13 @@ export default { |
|
|
|
getReturnList(params).then(({ data }) => { |
|
|
|
this.loading = false; |
|
|
|
if (data && data.code === 0) { |
|
|
|
this.returnList = data.data || []; |
|
|
|
// 为每个退货单添加展开状态和明细数据 |
|
|
|
this.returnList = (data.data || []).map(item => ({ |
|
|
|
...item, |
|
|
|
showDetails: false, |
|
|
|
detailsLoading: false, |
|
|
|
detailCards: [] |
|
|
|
})); |
|
|
|
} else { |
|
|
|
this.$message.error(data.msg || '获取数据失败'); |
|
|
|
} |
|
|
|
@ -144,7 +208,13 @@ export default { |
|
|
|
if (data.data.length === 0) { |
|
|
|
this.$message.warning('未找到匹配的退货单'); |
|
|
|
} |
|
|
|
this.returnList = data.data || []; |
|
|
|
// 为每个退货单添加展开状态和明细数据 |
|
|
|
this.returnList = (data.data || []).map(item => ({ |
|
|
|
...item, |
|
|
|
showDetails: false, |
|
|
|
detailsLoading: false, |
|
|
|
detailCards: [] |
|
|
|
})); |
|
|
|
} else { |
|
|
|
this.$message.error(data.msg || '查询失败'); |
|
|
|
} |
|
|
|
@ -155,13 +225,66 @@ export default { |
|
|
|
}); |
|
|
|
}, |
|
|
|
|
|
|
|
// 切换明细卡片显示 |
|
|
|
toggleDetailCards(item) { |
|
|
|
// 阻止事件冒泡 |
|
|
|
event.stopPropagation(); |
|
|
|
|
|
|
|
// 切换展开状态 |
|
|
|
item.showDetails = !item.showDetails; |
|
|
|
|
|
|
|
// 如果展开且还未加载过明细数据,则加载 |
|
|
|
if (item.showDetails && item.detailCards.length === 0 && !item.detailsLoading) { |
|
|
|
this.loadDetailCards(item); |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
// 加载明细卡片列表 |
|
|
|
loadDetailCards(item) { |
|
|
|
const currentWarehouse = getCurrentWarehouse(); |
|
|
|
if (!currentWarehouse) { |
|
|
|
this.$message.error('请先选择仓库'); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
item.detailsLoading = true; |
|
|
|
const params = { |
|
|
|
site: localStorage.getItem('site'), |
|
|
|
buNo: item.buNo, |
|
|
|
returnNo: item.returnNo, |
|
|
|
warehouseId: currentWarehouse, |
|
|
|
searchCode: this.searchCode |
|
|
|
}; |
|
|
|
|
|
|
|
getReturnDetailCards(params).then(({ data }) => { |
|
|
|
item.detailsLoading = false; |
|
|
|
if (data && data.code === 0) { |
|
|
|
item.detailCards = data.data || []; |
|
|
|
} else { |
|
|
|
this.$message.error(data.msg || '获取明细数据失败'); |
|
|
|
item.detailCards = []; |
|
|
|
} |
|
|
|
}).catch(error => { |
|
|
|
item.detailsLoading = false; |
|
|
|
console.error('获取明细数据失败:', error); |
|
|
|
this.$message.error('获取明细数据失败'); |
|
|
|
item.detailCards = []; |
|
|
|
}); |
|
|
|
}, |
|
|
|
|
|
|
|
// 跳转到退货页面 |
|
|
|
goToReturnPage(item) { |
|
|
|
goToReturnPage(item, detail) { |
|
|
|
// 阻止事件冒泡 |
|
|
|
event.stopPropagation(); |
|
|
|
|
|
|
|
this.$router.push({ |
|
|
|
name: 'purchaseReturnDetail', |
|
|
|
params: { |
|
|
|
buNo: item.buNo, |
|
|
|
returnNo: item.returnNo |
|
|
|
returnNo: item.returnNo, |
|
|
|
relatedNo: detail.relatedNo, |
|
|
|
relatedLineNo: detail.relatedLineNo, |
|
|
|
partNo: detail.partNo |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
@ -234,34 +357,47 @@ export default { |
|
|
|
padding: 12px 16px; |
|
|
|
} |
|
|
|
|
|
|
|
/* 退货卡片 */ |
|
|
|
.return-card { |
|
|
|
/* 退货组 */ |
|
|
|
.return-group { |
|
|
|
margin-bottom: 12px; |
|
|
|
} |
|
|
|
|
|
|
|
/* 主信息卡片 */ |
|
|
|
.return-card.main-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; |
|
|
|
margin-bottom: 0; |
|
|
|
} |
|
|
|
|
|
|
|
.return-card:hover { |
|
|
|
.return-card.main-card:hover { |
|
|
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); |
|
|
|
transform: translateY(-1px); |
|
|
|
} |
|
|
|
|
|
|
|
.return-card:active { |
|
|
|
.return-card.main-card:active { |
|
|
|
transform: translateY(0); |
|
|
|
} |
|
|
|
|
|
|
|
/* 卡片头部(包含标题和展开图标) */ |
|
|
|
.card-header { |
|
|
|
display: flex; |
|
|
|
justify-content: space-between; |
|
|
|
align-items: center; |
|
|
|
margin-bottom: 12px; |
|
|
|
} |
|
|
|
|
|
|
|
/* 卡片标题 */ |
|
|
|
.card-title { |
|
|
|
margin-bottom: 12px; |
|
|
|
flex: 1; |
|
|
|
} |
|
|
|
|
|
|
|
.title-label { |
|
|
|
font-size: 12px; |
|
|
|
color: #666; |
|
|
|
color: #999; |
|
|
|
display: block; |
|
|
|
margin-bottom: 4px; |
|
|
|
} |
|
|
|
@ -273,49 +409,225 @@ export default { |
|
|
|
margin-left: 20px; |
|
|
|
} |
|
|
|
|
|
|
|
/* 展开图标 */ |
|
|
|
.expand-icon { |
|
|
|
font-size: 18px; |
|
|
|
color: #17B3A3; |
|
|
|
transition: transform 0.3s ease; |
|
|
|
} |
|
|
|
|
|
|
|
.expand-icon.expanded { |
|
|
|
transform: rotate(180deg); |
|
|
|
} |
|
|
|
|
|
|
|
/* 卡片详情 */ |
|
|
|
.card-details { |
|
|
|
display: flex; |
|
|
|
justify-content: space-between; |
|
|
|
align-items: flex-start; |
|
|
|
gap: 4px; |
|
|
|
flex-direction: column; |
|
|
|
gap: 8px; |
|
|
|
} |
|
|
|
|
|
|
|
.detail-row { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
} |
|
|
|
|
|
|
|
.detail-item { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
flex: 1; |
|
|
|
text-align: center; |
|
|
|
min-width: 60px; |
|
|
|
max-width: 60px; |
|
|
|
} |
|
|
|
|
|
|
|
.detail-item.full-width { |
|
|
|
width: 100%; |
|
|
|
} |
|
|
|
|
|
|
|
.detail-label { |
|
|
|
font-size: 11px; |
|
|
|
font-size: 12px; |
|
|
|
color: #666; |
|
|
|
margin-bottom: 4px; |
|
|
|
line-height: 1.2; |
|
|
|
margin-left: -12px; |
|
|
|
margin-right: 8px; |
|
|
|
} |
|
|
|
|
|
|
|
.detail-value { |
|
|
|
font-size: 13px; |
|
|
|
font-size: 14px; |
|
|
|
color: #333; |
|
|
|
line-height: 1.2; |
|
|
|
margin-left: -12px; |
|
|
|
font-weight: 500; |
|
|
|
} |
|
|
|
|
|
|
|
.detail-value .qualified { |
|
|
|
.detail-value.customer-name { |
|
|
|
color: #17B3A3; |
|
|
|
font-weight: 500; |
|
|
|
flex: 1; |
|
|
|
overflow: hidden; |
|
|
|
text-overflow: ellipsis; |
|
|
|
white-space: nowrap; |
|
|
|
} |
|
|
|
|
|
|
|
/* 明细卡片容器 */ |
|
|
|
.detail-cards-container { |
|
|
|
padding: 12px 0 0 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* 明细卡片 */ |
|
|
|
.detail-card { |
|
|
|
background: #f8f9fa; |
|
|
|
border-radius: 6px; |
|
|
|
padding: 12px; |
|
|
|
margin-bottom: 8px; |
|
|
|
border-left: 3px solid #17B3A3; |
|
|
|
cursor: pointer; |
|
|
|
transition: all 0.2s ease; |
|
|
|
} |
|
|
|
|
|
|
|
.detail-value .total { |
|
|
|
.detail-card:hover { |
|
|
|
background: #e9ecef; |
|
|
|
transform: translateX(3px); |
|
|
|
} |
|
|
|
|
|
|
|
.detail-card:active { |
|
|
|
transform: translateX(0); |
|
|
|
} |
|
|
|
|
|
|
|
/* 明细卡片头部 */ |
|
|
|
.detail-card-header { |
|
|
|
margin-bottom: 8px; |
|
|
|
} |
|
|
|
|
|
|
|
.part-info { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
} |
|
|
|
|
|
|
|
.part-label { |
|
|
|
font-size: 11px; |
|
|
|
color: #666; |
|
|
|
margin-right: 6px; |
|
|
|
} |
|
|
|
|
|
|
|
.part-value { |
|
|
|
font-size: 14px; |
|
|
|
font-weight: bold; |
|
|
|
color: #333; |
|
|
|
font-weight: 500; |
|
|
|
} |
|
|
|
|
|
|
|
.detail-value .total::before { |
|
|
|
content: '/'; |
|
|
|
/* 明细卡片主体 */ |
|
|
|
.detail-card-body { |
|
|
|
margin-bottom: 8px; |
|
|
|
} |
|
|
|
|
|
|
|
.part-desc { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
margin-bottom: 6px; |
|
|
|
} |
|
|
|
|
|
|
|
.desc-label { |
|
|
|
font-size: 11px; |
|
|
|
color: #666; |
|
|
|
margin-right: 6px; |
|
|
|
} |
|
|
|
|
|
|
|
.desc-value { |
|
|
|
font-size: 12px; |
|
|
|
color: #333; |
|
|
|
flex: 1; |
|
|
|
} |
|
|
|
|
|
|
|
.quantity-info { |
|
|
|
display: flex; |
|
|
|
gap: 16px; |
|
|
|
} |
|
|
|
|
|
|
|
.qty-item { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
} |
|
|
|
|
|
|
|
.qty-label { |
|
|
|
font-size: 11px; |
|
|
|
color: #666; |
|
|
|
margin-right: 4px; |
|
|
|
} |
|
|
|
|
|
|
|
.qty-value { |
|
|
|
font-size: 13px; |
|
|
|
color: #333; |
|
|
|
font-weight: 500; |
|
|
|
} |
|
|
|
|
|
|
|
.qty-value.highlight { |
|
|
|
color: #17B3A3; |
|
|
|
font-weight: bold; |
|
|
|
} |
|
|
|
|
|
|
|
/* 明细卡片底部 */ |
|
|
|
.detail-card-footer { |
|
|
|
display: flex; |
|
|
|
justify-content: space-between; |
|
|
|
align-items: center; |
|
|
|
padding-top: 6px; |
|
|
|
border-top: 1px dashed #dee2e6; |
|
|
|
gap: 12px; |
|
|
|
} |
|
|
|
|
|
|
|
.footer-item { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
flex: 1; |
|
|
|
} |
|
|
|
|
|
|
|
.related-label { |
|
|
|
font-size: 11px; |
|
|
|
color: #999; |
|
|
|
margin-right: 4px; |
|
|
|
white-space: nowrap; |
|
|
|
} |
|
|
|
|
|
|
|
.related-value { |
|
|
|
font-size: 11px; |
|
|
|
color: #666; |
|
|
|
font-weight: 500; |
|
|
|
} |
|
|
|
|
|
|
|
/* 明细加载状态 */ |
|
|
|
.detail-loading { |
|
|
|
display: flex; |
|
|
|
flex-direction: column; |
|
|
|
align-items: center; |
|
|
|
justify-content: center; |
|
|
|
padding: 20px; |
|
|
|
color: #17B3A3; |
|
|
|
} |
|
|
|
|
|
|
|
.detail-loading i { |
|
|
|
font-size: 20px; |
|
|
|
margin-bottom: 8px; |
|
|
|
animation: spin 1s linear infinite; |
|
|
|
} |
|
|
|
|
|
|
|
.detail-loading p { |
|
|
|
font-size: 12px; |
|
|
|
margin: 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* 无明细数据 */ |
|
|
|
.no-details { |
|
|
|
display: flex; |
|
|
|
flex-direction: column; |
|
|
|
align-items: center; |
|
|
|
justify-content: center; |
|
|
|
padding: 20px; |
|
|
|
color: #999; |
|
|
|
} |
|
|
|
|
|
|
|
.no-details i { |
|
|
|
font-size: 24px; |
|
|
|
margin-bottom: 8px; |
|
|
|
} |
|
|
|
|
|
|
|
.no-details p { |
|
|
|
font-size: 12px; |
|
|
|
margin: 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* 空状态 */ |
|
|
|
|