|
|
@@ -1,21 +1,11 @@
|
|
|
<template>
|
|
|
- <ele-modal
|
|
|
- :width="800"
|
|
|
- v-model="visible"
|
|
|
- title="缺货退款"
|
|
|
- @open="handleOpen"
|
|
|
- :body-style="{ padding: '20px' }"
|
|
|
- >
|
|
|
+ <ele-modal :width="800" v-model="visible" title="缺货退款" @open="handleOpen" :body-style="{ padding: '20px' }">
|
|
|
<div class="refund-container">
|
|
|
<div class="section-title">选择要退款的商品及数量</div>
|
|
|
-
|
|
|
- <el-table
|
|
|
- ref="tableRef"
|
|
|
- :data="order?.products || []"
|
|
|
+
|
|
|
+ <el-table ref="tableRef" :data="order?.products || []"
|
|
|
style="width: 100%; border: 1px solid #ebeef5; border-bottom: none;"
|
|
|
- @selection-change="handleSelectionChange"
|
|
|
- header-row-class-name="custom-header"
|
|
|
- >
|
|
|
+ @selection-change="handleSelectionChange" header-row-class-name="custom-header">
|
|
|
<el-table-column type="selection" width="55" />
|
|
|
<el-table-column label="商品信息">
|
|
|
<template #default="{ row }">
|
|
|
@@ -27,14 +17,8 @@
|
|
|
</el-table-column>
|
|
|
<el-table-column label="数量" width="150">
|
|
|
<template #default="{ row }">
|
|
|
- <el-input-number
|
|
|
- v-model="row.refundQty"
|
|
|
- :min="1"
|
|
|
- :max="row.qty"
|
|
|
- size="small"
|
|
|
- controls-position="right"
|
|
|
- style="width: 100px;"
|
|
|
- />
|
|
|
+ <el-input-number v-model="row.refundQty" :min="1" :max="row.qty" size="small"
|
|
|
+ controls-position="right" style="width: 100px;" />
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="单价" width="120">
|
|
|
@@ -43,9 +27,6 @@
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
- <!-- Fill empty rows to mimic design height if needed, but el-table auto height is better.
|
|
|
- Design shows empty grid lines, which el-table does by default if data is short? No.
|
|
|
- We'll stick to standard table. -->
|
|
|
|
|
|
<div class="refund-summary mt-4">
|
|
|
<div class="summary-item">
|
|
|
@@ -55,11 +36,7 @@
|
|
|
</div>
|
|
|
<div class="summary-item items-center">
|
|
|
<span class="label">退还运费:</span>
|
|
|
- <el-input
|
|
|
- v-model="shippingRefund"
|
|
|
- style="width: 100px; margin-right: 10px;"
|
|
|
- placeholder="请输入"
|
|
|
- />
|
|
|
+ <el-input v-model="shippingRefund" style="width: 100px; margin-right: 10px;" placeholder="请输入" />
|
|
|
<span class="label">元</span>
|
|
|
<span class="warning-text">(不超过{{ maxShippingFee }}元)</span>
|
|
|
</div>
|
|
|
@@ -84,151 +61,154 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { ref, reactive, computed, watch } from 'vue';
|
|
|
-import { EleMessage } from 'ele-admin-plus/es';
|
|
|
-
|
|
|
-const visible = defineModel({ type: Boolean });
|
|
|
-const order = ref(null);
|
|
|
-const selectedRows = ref([]);
|
|
|
-const shippingRefund = ref(0);
|
|
|
-const sendCoupon = ref(true);
|
|
|
-const maxShippingFee = ref(5);
|
|
|
-
|
|
|
-const handleOpen = (row) => {
|
|
|
- // Deep copy to avoid mutating original list directly until save
|
|
|
- if (row) {
|
|
|
- order.value = JSON.parse(JSON.stringify(row));
|
|
|
- // Initialize refundQty for each product
|
|
|
- if (order.value.products) {
|
|
|
- order.value.products.forEach(p => {
|
|
|
- p.refundQty = p.qty; // Default to max qty
|
|
|
- });
|
|
|
+ import { ref, reactive, computed, watch } from 'vue';
|
|
|
+ import { EleMessage } from 'ele-admin-plus/es';
|
|
|
+
|
|
|
+ const visible = defineModel({ type: Boolean });
|
|
|
+ const order = ref(null);
|
|
|
+ const selectedRows = ref([]);
|
|
|
+ const shippingRefund = ref(0);
|
|
|
+ const sendCoupon = ref(true);
|
|
|
+ const maxShippingFee = ref(5);
|
|
|
+
|
|
|
+ const handleOpen = (row) => {
|
|
|
+ // Deep copy to avoid mutating original list directly until save
|
|
|
+ if (row) {
|
|
|
+ order.value = JSON.parse(JSON.stringify(row));
|
|
|
+ // Initialize refundQty for each product
|
|
|
+ if (order.value.products) {
|
|
|
+ order.value.products.forEach(p => {
|
|
|
+ p.refundQty = p.qty; // Default to max qty
|
|
|
+ });
|
|
|
+ }
|
|
|
+ shippingRefund.value = 0;
|
|
|
+ sendCoupon.value = true;
|
|
|
+ selectedRows.value = [];
|
|
|
+ }
|
|
|
+ visible.value = true;
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleSelectionChange = (val) => {
|
|
|
+ selectedRows.value = val;
|
|
|
+ };
|
|
|
+
|
|
|
+ // Computed
|
|
|
+ const productRefundAmount = computed(() => {
|
|
|
+ return selectedRows.value.reduce((sum, item) => {
|
|
|
+ return sum + (item.price * (item.refundQty || 0));
|
|
|
+ }, 0);
|
|
|
+ });
|
|
|
+
|
|
|
+ const selectedCount = computed(() => {
|
|
|
+ return selectedRows.value.reduce((sum, item) => {
|
|
|
+ return sum + (item.refundQty || 0);
|
|
|
+ }, 0);
|
|
|
+ });
|
|
|
+
|
|
|
+ const totalRefundAmount = computed(() => {
|
|
|
+ const shipping = parseFloat(shippingRefund.value) || 0;
|
|
|
+ return productRefundAmount.value + shipping;
|
|
|
+ });
|
|
|
+
|
|
|
+ const originalTotal = computed(() => {
|
|
|
+ return order.value?.payment?.total || 0;
|
|
|
+ });
|
|
|
+
|
|
|
+ const newTotal = computed(() => {
|
|
|
+ const val = originalTotal.value - totalRefundAmount.value;
|
|
|
+ return val > 0 ? val : 0;
|
|
|
+ });
|
|
|
+
|
|
|
+ const handleSubmit = () => {
|
|
|
+ if (selectedRows.value.length === 0 && parseFloat(shippingRefund.value) <= 0) {
|
|
|
+ EleMessage.warning('请选择退款商品或输入退款运费');
|
|
|
+ return;
|
|
|
}
|
|
|
- shippingRefund.value = 0;
|
|
|
- sendCoupon.value = true;
|
|
|
- selectedRows.value = [];
|
|
|
- }
|
|
|
- visible.value = true;
|
|
|
-};
|
|
|
-
|
|
|
-const handleSelectionChange = (val) => {
|
|
|
- selectedRows.value = val;
|
|
|
-};
|
|
|
-
|
|
|
-// Computed
|
|
|
-const productRefundAmount = computed(() => {
|
|
|
- return selectedRows.value.reduce((sum, item) => {
|
|
|
- return sum + (item.price * (item.refundQty || 0));
|
|
|
- }, 0);
|
|
|
-});
|
|
|
-
|
|
|
-const selectedCount = computed(() => {
|
|
|
- return selectedRows.value.reduce((sum, item) => {
|
|
|
- return sum + (item.refundQty || 0);
|
|
|
- }, 0);
|
|
|
-});
|
|
|
-
|
|
|
-const totalRefundAmount = computed(() => {
|
|
|
- const shipping = parseFloat(shippingRefund.value) || 0;
|
|
|
- return productRefundAmount.value + shipping;
|
|
|
-});
|
|
|
-
|
|
|
-const originalTotal = computed(() => {
|
|
|
- return order.value?.payment?.total || 0;
|
|
|
-});
|
|
|
-
|
|
|
-const newTotal = computed(() => {
|
|
|
- const val = originalTotal.value - totalRefundAmount.value;
|
|
|
- return val > 0 ? val : 0;
|
|
|
-});
|
|
|
-
|
|
|
-const handleSubmit = () => {
|
|
|
- if (selectedRows.value.length === 0 && parseFloat(shippingRefund.value) <= 0) {
|
|
|
- EleMessage.warning('请选择退款商品或输入退款运费');
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- const shipping = parseFloat(shippingRefund.value) || 0;
|
|
|
- if (shipping > maxShippingFee.value) {
|
|
|
- EleMessage.error(`退还运费不能超过${maxShippingFee.value}元`);
|
|
|
- return;
|
|
|
- }
|
|
|
|
|
|
- EleMessage.success('退款申请已提交');
|
|
|
- visible.value = false;
|
|
|
-};
|
|
|
+ const shipping = parseFloat(shippingRefund.value) || 0;
|
|
|
+ if (shipping > maxShippingFee.value) {
|
|
|
+ EleMessage.error(`退还运费不能超过${maxShippingFee.value}元`);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ EleMessage.success('退款申请已提交');
|
|
|
+ visible.value = false;
|
|
|
+ };
|
|
|
|
|
|
-defineExpose({
|
|
|
- handleOpen
|
|
|
-});
|
|
|
+ defineExpose({
|
|
|
+ handleOpen
|
|
|
+ });
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
-.refund-container {
|
|
|
- .section-title {
|
|
|
- font-weight: bold;
|
|
|
- margin-bottom: 10px;
|
|
|
- font-size: 14px;
|
|
|
- color: #303133;
|
|
|
- }
|
|
|
-
|
|
|
- .product-info {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- .product-img {
|
|
|
- width: 50px;
|
|
|
- height: 50px;
|
|
|
- margin-right: 10px;
|
|
|
- border-radius: 4px;
|
|
|
- }
|
|
|
- .product-title {
|
|
|
- font-size: 13px;
|
|
|
- line-height: 1.4;
|
|
|
+ .refund-container {
|
|
|
+ .section-title {
|
|
|
+ font-weight: bold;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #303133;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- .refund-summary {
|
|
|
- font-size: 14px;
|
|
|
- color: #606266;
|
|
|
-
|
|
|
- .summary-item {
|
|
|
+ .product-info {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
- margin-bottom: 10px;
|
|
|
- line-height: 24px;
|
|
|
-
|
|
|
- .label {
|
|
|
- font-weight: bold;
|
|
|
- color: #303133;
|
|
|
- }
|
|
|
-
|
|
|
- .value {
|
|
|
- color: #303133;
|
|
|
- font-weight: bold;
|
|
|
- }
|
|
|
-
|
|
|
- .total-amount {
|
|
|
- color: #f56c6c;
|
|
|
- font-weight: bold;
|
|
|
- font-size: 16px;
|
|
|
+
|
|
|
+ .product-img {
|
|
|
+ width: 50px;
|
|
|
+ height: 50px;
|
|
|
+ margin-right: 10px;
|
|
|
+ border-radius: 4px;
|
|
|
}
|
|
|
-
|
|
|
- .sub-text {
|
|
|
- color: #909399;
|
|
|
- margin-left: 5px;
|
|
|
+
|
|
|
+ .product-title {
|
|
|
font-size: 13px;
|
|
|
+ line-height: 1.4;
|
|
|
}
|
|
|
-
|
|
|
- .warning-text {
|
|
|
- color: #303133;
|
|
|
- font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ .refund-summary {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #606266;
|
|
|
+
|
|
|
+ .summary-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ line-height: 24px;
|
|
|
+
|
|
|
+ .label {
|
|
|
+ font-weight: bold;
|
|
|
+ color: #303133;
|
|
|
+ }
|
|
|
+
|
|
|
+ .value {
|
|
|
+ color: #303133;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ .total-amount {
|
|
|
+ color: #f56c6c;
|
|
|
+ font-weight: bold;
|
|
|
+ font-size: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-text {
|
|
|
+ color: #909399;
|
|
|
+ margin-left: 5px;
|
|
|
+ font-size: 13px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .warning-text {
|
|
|
+ color: #303133;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-}
|
|
|
-:deep(.custom-header) th {
|
|
|
- background-color: #f5f7fa !important;
|
|
|
- color: #606266;
|
|
|
- font-weight: normal;
|
|
|
-}
|
|
|
+
|
|
|
+ :deep(.custom-header) th {
|
|
|
+ background-color: #f5f7fa !important;
|
|
|
+ color: #606266;
|
|
|
+ font-weight: normal;
|
|
|
+ }
|
|
|
</style>
|