Browse Source

2025-11-03

pda采购退货优化
master
fengyuan_yang 2 months ago
parent
commit
06337abf25
  1. 6
      src/api/purchase/purchase-return.js
  2. 398
      src/views/modules/purchase-return/purchaseReturnList.vue

6
src/api/purchase/purchase-return.js

@ -29,3 +29,9 @@ export const confirmPurchaseReturn = data => createAPI(`purchaseReturn/confirmPu
* @param {Object} data - 查询参数 {site, buNo, returnNo}
*/
export const getMaterialList = data => createAPI(`purchaseReturn/getMaterialList`, 'post', data)
/**
* 获取采购退货单明细卡片列表
* @param {Object} data - 查询参数 {site, buNo, returnNo, warehouseId, searchCode}
*/
export const getReturnDetailCards = data => createAPI(`purchaseReturn/getReturnDetailCards`, 'post', data)

398
src/views/modules/purchase-return/purchaseReturnList.vue

@ -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;
}
/* 空状态 */

Loading…
Cancel
Save