javacodeadmin/ruoyi-ui/src/views/system/GoodsOrder/index.vue

1719 lines
48 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<!-- 搜索表单 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="订单号" prop="mainOrderId">
<el-input
v-model="queryParams.mainOrderId"
placeholder="请输入订单号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="支付单号" prop="transactionId">
<el-input
v-model="queryParams.transactionId"
placeholder="请输入微信支付单号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="用户" prop="uid">
<user-select
v-model="queryParams.uid"
placeholder="请选择用户"
user-type="1"
dialog-title="选择用户"
style="width: 200px;"
/>
</el-form-item>
<el-form-item label="商品" prop="productId">
<el-select v-model="queryParams.productId" placeholder="请选择商品" clearable filterable>
<el-option v-for="item in goodsDataList" :key="item.id" :label="item.title" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="订单状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
<el-option label="待支付" :value="1" />
<el-option label="已支付待发货" :value="2" />
<el-option label="已发货" :value="3" />
<el-option label="待评价" :value="4" />
<el-option label="已完成" :value="5" />
<el-option label="已取消" :value="6" />
<el-option label="申请退款" :value="20" />
<el-option label="同意退款" :value="21" />
<el-option label="驳回退款" :value="22" />
</el-select>
</el-form-item>
<el-form-item label="支付金额" prop="priceRange">
<el-input
v-model="queryParams.payPriceMin"
placeholder="最低价"
style="width: 100px; margin-right: 10px;"
type="number"
min="0"
clearable
/>
<span style="margin: 0 5px;">-</span>
<el-input
v-model="queryParams.payPriceMax"
placeholder="最高价"
style="width: 100px;"
type="number"
min="0"
clearable
/>
</el-form-item>
<el-form-item label="支付时间">
<el-date-picker
v-model="daterangePayTime"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="daterangeCreatedAt"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
<el-button type="info" icon="el-icon-arrow-down" size="mini" @click="toggleAdvancedSearch">
{{ showAdvancedSearch ? '收起' : '高级搜索' }}
</el-button>
</el-form-item>
</el-form>
<!-- 高级搜索表单 -->
<el-form
v-show="showAdvancedSearch"
:model="queryParams"
ref="advancedForm"
size="small"
:inline="true"
label-width="80px"
class="advanced-search-form"
>
<el-form-item label="收货人" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入收货人姓名"
clearable
style="width: 150px;"
/>
</el-form-item>
<el-form-item label="联系电话" prop="phone">
<el-input
v-model="queryParams.phone"
placeholder="请输入联系电话"
clearable
style="width: 150px;"
/>
</el-form-item>
<el-form-item label="商品类型" prop="type">
<el-select v-model="queryParams.type" placeholder="请选择类型" clearable style="width: 150px;">
<el-option label="服务项目" :value="1" />
<el-option label="商品" :value="2" />
</el-select>
</el-form-item>
<el-form-item label="是否自提" prop="isself">
<el-select v-model="queryParams.isself" placeholder="请选择" clearable style="width: 150px;">
<el-option label="是" :value="1" />
<el-option label="否" :value="2" />
</el-select>
</el-form-item>
<el-form-item label="售后状态" prop="returnstatus">
<el-select v-model="queryParams.returnstatus" placeholder="请选择售后状态" clearable style="width: 150px;">
<el-option label="无售后" :value="0" />
<el-option label="用户申请" :value="1" />
<el-option label="平台同意" :value="2" />
<el-option label="用户添加物流" :value="3" />
<el-option label="平台收货" :value="4" />
<el-option label="平台退款" :value="5" />
<el-option label="平台驳回" :value="6" />
<el-option label="用户取消售后" :value="7" />
<el-option label="退款失败" :value="8" />
</el-select>
</el-form-item>
</el-form>
<!-- 操作按钮 -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-upload2"
size="mini"
@click="handleExcelImport"
v-hasPermi="['system:GoodsOrder:edit']"
>Excel批量发货</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-download"
size="mini"
@click="handleExportData"
v-hasPermi="['system:GoodsOrder:export']"
>导出数据</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<!-- 数据表格 -->
<el-table
v-loading="loading"
:data="GoodsOrderList"
@selection-change="handleSelectionChange"
border
>
<el-table-column type="selection" width="55" align="center" />
<!-- 订单基本信息 -->
<el-table-column label="主订单号" align="center" prop="mainOrderId" class-name="order-column" />
<el-table-column label="订单状态" align="center" prop="status" class-name="order-column">
<template slot-scope="scope">
<dict-tag :options="dict.type.goods_order_status" :value="scope.row.status"/>
</template>
</el-table-column>
<!-- 商品信息 -->
<el-table-column label="商品" align="center" prop="productName" class-name="product-column">
<template slot-scope="scope">
<div>
<!-- 显示商品信息 -->
<div class="single-product" v-for="value in (scope.row.children && scope.row.children.length > 0 ? scope.row.children : [scope.row])" :key="value.id || value.orderId">
<el-tag size="mini" type="success">
{{ value.productName || '未知商品' }}
</el-tag>
<span style="margin-left: 5px; color: #666; font-size: 12px;">
x{{ value.num || 0 }}
</span>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="数量" align="center" width="65" prop="num" class-name="product-column" />
<!-- 金额信息 -->
<el-table-column label="总价" width="100px" align="center" prop="totalPrice" class-name="amount-column">
<template slot-scope="scope">
<span class="amount-total">¥{{scope.row.totalPrice ? scope.row.totalPrice.toFixed(2) : '0.00'}}</span>
</template>
</el-table-column>
<el-table-column label="支付金额" width="100px" align="center" prop="payPrice" class-name="amount-column">
<template slot-scope="scope">
<span
class="amount-pay"
style="cursor: pointer; text-decoration: underline;"
@click="handlePrePaymentClick(scope.row)"
>¥{{scope.row.payPrice ? scope.row.payPrice.toFixed(2) : '0.00'}}</span>
</template>
</el-table-column>
<el-table-column label="抵扣金额" width="100px" align="center" prop="deduction" class-name="amount-column">
<template slot-scope="scope">
<span class="amount-deduction">¥{{scope.row.deduction ? scope.row.deduction.toFixed(2) : '0.00'}}</span>
</template>
</el-table-column>
<!-- 用户信息 -->
<el-table-column label="姓名" align="center" width="75" prop="name" class-name="user-column" />
<el-table-column label="电话" align="center" width="125" prop="phone" class-name="user-column" />
<!-- 时间信息 -->
<el-table-column label="支付时间" align="center" prop="payTime" width="120" class-name="time-column">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.payTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createdAt" width="120" class-name="time-column">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createdAt, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="更新时间" align="center" prop="updatedAt" width="120" class-name="time-column">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.updatedAt, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
<template slot-scope="scope">
<!-- 发货按钮 - 只有已支付待发货状态的订单才显示 -->
<el-button
v-if="scope.row.status === 2"
size="mini"
type="text"
icon="el-icon-sell"
@click="handleShip(scope.row)"
style="color: #67C23A;"
>发货</el-button>
<!-- 售后按钮 - 只有状态大于等于20的订单才显示 -->
<el-button
v-if="scope.row.status >= 15"
size="mini"
type="text"
icon="el-icon-service"
@click="handleAfterSale(scope.row)"
style="color: #E6A23C;"
>售后</el-button>
<!-- v-if="scope.row.status >= 15"-->
<!-- 统一退款按钮 -->
<el-button
v-if="scope.row.status >= 15"
size="mini"
type="text"
icon="el-icon-money"
@click="handleUnifiedRefund(scope.row)"
style="color: #67C23A;"
>统一退款</el-button>
<!-- 如果是主行,显示查看详情按钮 -->
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handleViewDetails(scope.row)"
style="color: #909399;"
>查看详情</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['system:GoodsOrder:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 售后详情对话框 -->
<AfterSaleDialog
:visible.sync="afterSaleDialogVisible"
:currentAfterSaleOrder="currentAfterSaleOrder"
:showAfterSaleActions="showAfterSaleActions"
:showPlatformActions="showPlatformActions"
:returnStatusMap="returnStatusMap"
@close="handleAfterSaleClose"
@reject-after-sale="handleRejectAfterSale"
@approve-after-sale="handleApproveAfterSale"
@reject-refund="handleRejectRefund"
@refund-success="handleRefundSuccess"
/>
<!-- 驳回理由输入对话框 -->
<RejectReasonDialog
:visible.sync="rejectReasonDialogVisible"
:form="rejectReasonForm"
:rules="rejectReasonRules"
@cancel="rejectReasonDialogVisible = false"
@confirm="submitRejectReason"
/>
<!-- 退款金额输入对话框 -->
<RefundAmountDialog
:visible.sync="refundAmountDialogVisible"
:form="refundAmountForm"
:rules="refundAmountRules"
@cancel="refundAmountDialogVisible = false"
@confirm="submitRefundAmount"
/>
<!-- 发货对话框 -->
<ShipmentDialog
:visible.sync="shipDialogVisible"
:currentShipOrder="currentShipOrder"
:shipmentOrders="shipmentOrders"
:deliveryList="deliveryList"
:shipForm="shipForm"
:shipRules="shipRules"
:shipMode="shipMode"
:loading="shipLoading"
@cancel="handleShipClose"
@confirm="handleShipConfirm"
/>
<!-- Excel导入发货对话框 -->
<ExcelImportDialog
:visible.sync="excelImportDialogVisible"
:form="excelImportForm"
:rules="excelImportRules"
:loading="excelImportLoading"
@cancel="excelImportDialogVisible = false"
@confirm="submitExcelImport"
@file-change="handleFileChange"
@file-remove="handleFileRemove"
@before-upload="beforeUpload"
@download-template="downloadTemplate"
/>
<!-- Excel导入结果对话框 -->
<ImportResultDialog
:visible.sync="importResultVisible"
:importResult="importResult"
@close="importResultVisible = false"
@refresh="refreshOrderList"
/>
<!-- 订单详情组件 -->
<GoodsOrderDetails
:visible.sync="detailDialogVisible"
:orderId="currentDetailOrderId"
@refresh="getList"
/>
<!-- 预支付数据对话框 -->
<prePaymentDialog
:visible.sync="prePaymentDialogVisible"
:prePaymentData="prePaymentData"
@close="handlePrePaymentClose"
/>
<!-- 统一退款对话框 -->
<UnifiedRefundDialog
:visible.sync="unifiedRefundDialogVisible"
:orderId="currentRefundOrder ? currentRefundOrder.mainOrderId : ''"
:paymentData="currentRefundPaymentData"
@success="handleRefundSuccess"
/>
</div>
</template>
<script>
import { listGoodsOrder, delGoodsOrder, getGoodsDataList, getSiteDeliveryList, processAfterSale, shipOrder, getPrePaymentByOrderId, batchShipByExcel, getGoodsOrderByMainOrderId} from "@/api/system/GoodsOrder"
export default {
name: "GoodsOrder",
dicts: ['goods_order_status'],
components: {
GoodsOrderDetails: () => import('./details.vue'),
AfterSaleDialog: () => import('./AfterSaleDialog.vue'),
RejectReasonDialog: () => import('./RejectReasonDialog.vue'),
RefundAmountDialog: () => import('./RefundAmountDialog.vue'),
ShipmentDialog: () => import('./ShipmentDialog.vue'),
ExcelImportDialog: () => import('./ExcelImportDialog.vue'),
ImportResultDialog: () => import('./ImportResultDialog.vue'),
PrePaymentDialog: () => import('./PrePaymentDialog.vue'),
UnifiedRefundDialog: () => import('./UnifiedRefundDialog.vue')
},
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 商品订单表格数据
GoodsOrderList: [],
// 快递公司列表
deliveryList: [],
// 商品数据列表
goodsDataList: [],
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
type: null,
mainOrderId: null,
orderId: null,
transactionId: null,
uid: null,
productId: null,
name: null,
phone: null,
address: null,
num: null,
totalPrice: null,
goodPrice: null,
servicePrice: null,
payPrice: null,
deduction: null,
postage: null,
payTime: null,
status: null,
deliveryId: null,
deliveryNum: null,
sendTime: null,
mark: null,
addressId: null,
sku: null,
createdAt: null,
updatedAt: null,
deletedAt: null,
//------------------
payPriceMin: null,
payPriceMax: null,
startdate: null,
enddate: null,
paystartdate: null,
payenddate: null
//------------------
},
daterangePayTime: [],
daterangeCreatedAt: [],
// 售后相关数据
currentAfterSaleOrder: null,
afterSaleDialogVisible: false,
// 售后状态映射
returnStatusMap: {
1: '用户申请',
2: '平台同意',
3: '用户添加物流',
4: '平台收货',
5: '平台退款',
6: '平台驳回',
7: '用户取消售后',
8: '退款失败'
},
// 发货相关数据
shipDialogVisible: false,
shipForm: {
id: null,
orderId: '',
productName: '',
name: '',
phone: '',
address: '',
deliveryId: null,
deliveryNum: '',
sendTime: '',
mark: ''
},
// 发货表单校验规则
shipRules: {
deliveryId: [
{ required: true, message: '请选择快递公司', trigger: 'change' }
],
deliveryNum: [
{ required: true, message: '请输入快递单号', trigger: 'blur' }
],
sendTime: [
{ required: true, message: '请选择发货时间', trigger: 'change' }
]
},
// 驳回理由输入对话框
rejectReasonDialogVisible: false,
rejectReasonForm: {
rejectReason: ''
},
rejectReasonRules: {
rejectReason: [
{ required: true, message: '驳回理由不能为空', trigger: 'blur' }
]
},
// 退款金额输入对话框
refundAmountDialogVisible: false,
refundAmountForm: {
orderAmount: '',
returnrealmoney: '',
refundRemark: ''
},
refundAmountRules: {
returnrealmoney: [
{ required: true, message: '退款金额不能为空', trigger: 'blur' },
{ min: 0, message: '退款金额不能小于0', trigger: 'blur' },
{
validator: (rule, value, callback) => {
if (value && this.refundAmountForm.orderAmount) {
const refundAmount = parseFloat(value);
const orderAmount = parseFloat(this.refundAmountForm.orderAmount);
if (refundAmount > orderAmount) {
callback(new Error('退款金额不能超过订单金额'));
} else {
callback();
}
} else {
callback();
}
},
trigger: 'blur'
}
],
refundRemark: [
{ max: 200, message: '退款备注不能超过200个字', trigger: 'blur' }
]
},
// 预支付数据对话框
prePaymentDialogVisible: false,
prePaymentData: null,
// Excel导入发货对话框
excelImportDialogVisible: false,
excelImportForm: {
file: null
},
excelImportRules: {
file: [
{ required: true, message: '请选择Excel文件', trigger: 'change' }
]
},
// Excel导入结果
importResult: null,
importResultVisible: false,
// Excel导入加载状态
excelImportLoading: false,
// 查看详情相关
currentDetailOrder: null,
currentDetailOrderId: null,
detailDialogVisible: false,
// 高级搜索相关
showAdvancedSearch: false,
// 发货相关
shipMode: 'single',
currentShipOrder: null,
shipLoading: false,
shipmentOrders: [],
// 统一退款对话框相关
unifiedRefundDialogVisible: false,
currentRefundOrder: null,
currentRefundPaymentData: null
}
},
created() {
// 简化初始化
this.getList();
this.fetchGoodsDataList();
this.getdeliveryList();
// 确保对话框状态正确
this.afterSaleDialogVisible = false;
this.rejectReasonDialogVisible = false;
this.refundAmountDialogVisible = false;
this.shipDialogVisible = false;
this.prePaymentDialogVisible = false;
this.excelImportDialogVisible = false;
this.importResultVisible = false;
this.detailDialogVisible = false;
this.unifiedRefundDialogVisible = false;
this.currentRefundOrder = null;
this.currentRefundPaymentData = null;
},
mounted() {
// 简化mounted钩子
this.fetchGoodsDataList();
this.getdeliveryList();
},
beforeDestroy() {
// 简化清理逻辑
this.closeAllDialogs();
},
deactivated() {
// 组件停用时清理对话框
this.closeAllDialogs();
},
computed: {
/** 是否显示售后操作按钮 */
showAfterSaleActions() {
if (!this.currentAfterSaleOrder) return false;
return this.currentAfterSaleOrder.returnstatus === 1;
},
/** 是否显示平台收货后操作按钮 */
showPlatformActions() {
if (!this.currentAfterSaleOrder) return false;
return this.currentAfterSaleOrder.returnstatus === 4;
}
},
methods: {
groupedGoodsOrderList() {
// 防止在数据加载过程中意外触发弹窗
if (!this.GoodsOrderList || this.GoodsOrderList.length === 0) {
return;
}
this.GoodsOrderList.forEach((item, index) => {
if (item.mainOrderId) {
getGoodsOrderByMainOrderId(item.mainOrderId).then(response => {
this.$set(this.GoodsOrderList[index], 'children', response.data);
// 移除 $forceUpdate() 调用避免不必要的DOM更新
}).catch(error => {
console.warn('获取子订单失败:', error);
});
}
});
},
/** 查询商品订单列表 */
getList() {
// 关闭所有对话框和抽屉,防止数据不更新时弹窗意外打开
this.closeAllDialogs();
this.currentDetailOrder = {};
this.loading = true
listGoodsOrder(this.queryParams).then(response => {
this.GoodsOrderList = response.rows;
this.loading = false
this.groupedGoodsOrderList()
this.total = response.total
})
},
/** 搜索按钮操作 */
handleQuery() {
// 处理支付时间
if (this.daterangePayTime && this.daterangePayTime.length === 2) {
this.queryParams.paystartdate = this.daterangePayTime[0];
this.queryParams.payenddate = this.daterangePayTime[1];
} else {
this.queryParams.paystartdate = undefined;
this.queryParams.payenddate = undefined;
}
// 处理创建时间
if (this.daterangeCreatedAt && this.daterangeCreatedAt.length === 2) {
this.queryParams.startdate = this.daterangeCreatedAt[0];
this.queryParams.enddate = this.daterangeCreatedAt[1];
} else {
this.queryParams.startdate = undefined;
this.queryParams.enddate = undefined;
}
// 删除多余的 payTime 和 createdAt 字段,防止后台报错
delete this.queryParams.payTime;
delete this.queryParams.createdAt;
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.daterangePayTime = [];
this.daterangeCreatedAt = [];
this.resetForm("queryForm");
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
// 获取所有选中的行,包括子行
const allIds = [];
selection.forEach(row => {
if (row.isMainRow && row.children) {
// 如果是主行添加所有子行的ID
row.children.forEach(child => {
allIds.push(child.id);
});
} else {
// 如果是普通行直接添加ID
allIds.push(row.id);
}
});
this.ids = allIds;
this.single = selection.length !== 1;
this.multiple = !selection.length;
},
/** 删除按钮操作 */
handleDelete(row) {
let ids;
let message;
if (row.isMainRow && row.children && row.children.length > 1) {
// 如果是主行且有多个子订单,删除整个主订单
ids = row.children.map(child => child.id);
message = `是否确认删除主订单号为"${row.mainOrderId}"的所有数据项?共${row.children.length}个子订单`;
} else {
// 如果是单个订单或子订单
ids = row.id || this.ids;
message = '是否确认删除商品订单编号为"' + ids + '"的数据项?';
}
this.$modal.confirm(message).then(function() {
return delGoodsOrder(ids);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/** 关闭所有对话框 - 简化版本 */
closeAllDialogs() {
// 关闭所有对话框
this.afterSaleDialogVisible = false;
this.rejectReasonDialogVisible = false;
this.refundAmountDialogVisible = false;
this.shipDialogVisible = false;
this.prePaymentDialogVisible = false;
this.excelImportDialogVisible = false;
this.importResultVisible = false;
this.detailDialogVisible = false;
this.unifiedRefundDialogVisible = false;
this.currentRefundOrder = null;
this.currentRefundPaymentData = null;
// 使用nextTick确保弹窗完全关闭后再重置数据
this.$nextTick(() => {
// 重置相关数据,防止弹窗意外打开
this.currentAfterSaleOrder = null;
this.currentDetailOrder = null;
this.currentDetailOrderId = null;
this.currentShipOrder = null;
// 重置预支付数据
this.prePaymentData = null;
// 重置发货相关数据
this.shipmentOrders = [];
this.shipForm = {
id: null,
orderId: '',
productName: '',
name: '',
phone: '',
address: '',
deliveryId: null,
deliveryNum: '',
sendTime: '',
mark: ''
};
});
},
/** 售后按钮操作 */
handleAfterSale(row) {
// 先重置状态,确保弹窗能正常打开
this.currentAfterSaleOrder = null;
this.afterSaleDialogVisible = false;
// 使用nextTick确保DOM更新后再设置新状态
this.$nextTick(() => {
this.currentAfterSaleOrder = row;
this.afterSaleDialogVisible = true;
});
},
/** 获取售后状态对应的标签类型 */
getReturnStatusType(status) {
const typeMap = {
1: 'info', // 用户申请
2: 'success', // 平台同意
3: 'warning', // 用户添加物流
4: 'success', // 平台收货
5: 'success', // 平台退款
6: 'danger', // 平台驳回
7: 'info', // 用户取消售后
8: 'danger' // 退款失败
};
return typeMap[status] || 'info';
},
/** 处理售后操作 */
processAfterSaleAction(params) {
// 调用后端API
processAfterSale(params).then(response => {
if (response.code === 200) {
this.$modal.msgSuccess('操作成功');
this.closeAllDialogs();
// 重置售后相关数据
this.currentAfterSaleOrder = null;
// 刷新列表
this.getList();
} else {
this.$modal.msgError(response.msg || '操作失败');
}
}).catch(error => {
console.error('售后操作失败:', error);
this.$modal.msgError('操作失败,请重试');
});
},
/** 驳回售后申请 */
handleRejectAfterSale() {
this.rejectReasonForm.rejectReason = ''; // 清空驳回理由
this.rejectReasonDialogVisible = true;
},
/** 同意售后申请 */
handleApproveAfterSale() {
// 根据售后类型和状态决定是否需要退款
const { returntype, returnstatus } = this.currentAfterSaleOrder;
if (returntype === 1 && returnstatus === 1) {
// 仅退款且是初始申请状态,需要立即退款 - 打开统一退款页面
this.currentRefundPaymentData = {
wxmoney: this.currentAfterSaleOrder.payPrice || 0,
yemoney: 0,
shopmoney: 0,
servicemoney: 0,
membermoney: 0,
couponmoney: 0
};
this.unifiedRefundDialogVisible = true;
} else if (returntype === 2 && returnstatus === 4) {
// 退货退款且平台已收货,需要退款 - 打开统一退款页面
this.currentRefundPaymentData = {
wxmoney: this.currentAfterSaleOrder.payPrice || 0,
yemoney: 0,
shopmoney: 0,
servicemoney: 0,
membermoney: 0,
couponmoney: 0
};
this.unifiedRefundDialogVisible = true;
} else if (returntype === 2 && returnstatus === 1) {
// 退货退款且是初始申请状态,直接同意申请,不输入退款金额
this.$modal.confirm('确认同意该退货退款申请吗?客户需要先寄回商品。').then(() => {
const params = {
id: this.currentAfterSaleOrder.id,
action: 'approve'
};
this.processAfterSaleAction(params);
}).catch(() => {});
} else {
// 其他情况,直接同意申请
this.$modal.confirm('确认同意该售后申请吗?').then(() => {
const params = {
id: this.currentAfterSaleOrder.id,
action: 'approve'
};
this.processAfterSaleAction(params);
}).catch(() => {});
}
},
/** 驳回退款 */
handleRejectRefund() {
this.rejectReasonForm.rejectReason = ''; // 清空驳回理由
this.rejectReasonDialogVisible = true;
},
/** 处理退款成功 */
handleRefundSuccess() {
// 退款成功后刷新列表
this.getList();
this.$modal.msgSuccess('退款成功');
},
/** 提交驳回理由 */
submitRejectReason() {
this.$refs.rejectReasonForm.validate(valid => {
if (valid) {
// 判断是售后申请驳回还是退款驳回
const action = this.currentAfterSaleOrder.returnstatus === 1 ? 'reject' : 'reject_refund';
const params = {
id: this.currentAfterSaleOrder.id,
action: action,
rejectReason: this.rejectReasonForm.rejectReason
};
this.processAfterSaleAction(params);
}
});
},
/** 提交退款金额 */
submitRefundAmount() {
this.$refs.refundAmountForm.validate(valid => {
if (valid) {
// 验证退款金额不能超过订单金额
const refundAmount = parseFloat(this.refundAmountForm.returnrealmoney);
const orderAmount = parseFloat(this.refundAmountForm.orderAmount);
if (refundAmount > orderAmount) {
this.$modal.msgError('退款金额不能超过订单金额');
return;
}
// 根据当前状态决定action类型
const action = this.currentAfterSaleOrder.returnstatus === 1 ? 'approve' : 'approve_refund';
const params = {
id: this.currentAfterSaleOrder.id,
action: action,
returnrealmoney: this.refundAmountForm.returnrealmoney,
refundRemark: this.refundAmountForm.refundRemark
};
this.processAfterSaleAction(params);
}
});
},
/** 发货按钮操作 */
async handleShip(row) {
try {
// 先重置状态,确保弹窗能正常打开
this.currentShipOrder = null;
this.shipmentOrders = [];
this.shipDialogVisible = false;
// 使用nextTick确保DOM更新后再设置新状态
this.$nextTick(() => {
this.currentShipOrder = row;
this.shipMode = 'single';
// 设置单个发货表单数据
this.shipForm = {
id: row.id,
orderId: row.orderId,
productName: row.productName,
name: row.name,
phone: row.phone,
address: row.address,
deliveryId: null,
deliveryNum: '',
sendTime: '',
mark: ''
};
// 设置发货订单列表 - 如果有子订单则使用子订单,否则使用当前订单
if (row.children && row.children.length > 0) {
this.shipmentOrders = row.children;
} else {
this.shipmentOrders = [row];
}
this.shipDialogVisible = true;
});
} catch (error) {
console.error('获取发货数据失败:', error);
this.$modal.msgError('获取发货数据失败,请重试');
}
},
/** 提交发货表单 */
handleShipConfirm(shipFormData) {
this.shipLoading = true;
const shipData = {
id: this.currentShipOrder.id,
deliveryId: shipFormData.deliveryId,
deliveryNum: shipFormData.deliveryNum,
sendTime: shipFormData.sendTime,
mark: shipFormData.mark,
status: 3 // 设置为已发货状态
}
shipOrder(shipData).then(response => {
this.$modal.msgSuccess('发货成功')
this.shipDialogVisible = false
this.shipLoading = false;
// 重置发货相关数据
this.currentShipOrder = null;
this.shipmentOrders = [];
this.shipForm = {
id: null,
orderId: '',
productName: '',
name: '',
phone: '',
address: '',
deliveryId: null,
deliveryNum: '',
sendTime: '',
mark: ''
};
this.getList() // 刷新列表
}).catch(error => {
this.$modal.msgError('发货失败:' + (error.message || '未知错误'))
this.shipLoading = false;
})
},
/** 处理预支付数据点击 */
handlePrePaymentClick(row) {
// 先重置状态,确保弹窗能正常打开
this.prePaymentData = null;
this.prePaymentDialogVisible = false;
if (!row.orderId) {
this.$modal.msgWarning('该订单没有订单号');
return;
}
// 使用nextTick确保DOM更新后再设置新状态
this.$nextTick(() => {
// 调用API获取预支付数据
getPrePaymentByOrderId(row.orderId).then(response => {
if (response.code === 200) {
this.prePaymentData = response.data;
this.prePaymentDialogVisible = true;
} else {
this.$modal.msgError(response.msg || '获取预支付数据失败');
}
}).catch(error => {
console.error('获取预支付数据失败:', error);
this.$modal.msgError('获取预支付数据失败,请重试');
});
});
},
/** 处理Excel导入发货 */
handleExcelImport() {
// 先重置状态,确保弹窗能正常打开
this.excelImportDialogVisible = false;
this.excelImportForm.file = null;
// 使用nextTick确保DOM更新后再设置新状态
this.$nextTick(() => {
this.excelImportDialogVisible = true;
this.$nextTick(() => {
if (this.$refs.excelImportForm) {
this.$refs.excelImportForm.resetFields();
}
if (this.$refs.upload) {
this.$refs.upload.clearFiles();
}
});
});
},
/** 上传文件前的钩子 */
beforeUpload(file) {
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
this.$modal.msgError('上传文件大小不能超过 2MB!');
}
return isLt2M;
},
/** 文件选择改变时的钩子 */
handleFileChange(file, fileList) {
this.excelImportForm.file = file.raw;
},
/** 文件列表移除时的钩子 */
handleFileRemove(file, fileList) {
this.excelImportForm.file = null;
},
/** 文件上传成功时的钩子 */
handleFileSuccess(response, file, fileList) {
if (response.code === 200) {
this.$modal.msgSuccess('文件上传成功!');
this.excelImportForm.file = file;
} else {
this.$modal.msgError(response.msg || '文件上传失败!');
this.excelImportForm.file = file;
}
},
/** 提交Excel导入 */
submitExcelImport() {
if (!this.excelImportForm.file) {
this.$modal.msgError('请先选择Excel文件');
return;
}
this.$modal.confirm('确定要导入Excel文件吗这将批量处理订单发货。').then(() => {
this.excelImportLoading = true;
batchShipByExcel(this.excelImportForm.file).then(response => {
this.excelImportLoading = false;
if (response.code === 200) {
this.importResult = response.data;
this.importResultVisible = true;
this.excelImportDialogVisible = false;
this.getList(); // 刷新列表
} else {
this.$modal.msgError(response.msg || '导入失败!');
}
}).catch(error => {
this.excelImportLoading = false;
this.$modal.msgError('导入失败,请重试!' + (error.message || '未知错误'));
});
}).catch(() => {});
},
/** 下载Excel模板 */
downloadTemplate() {
// 直接在前端生成CSV模板
const csvContent = '订单号,快递公司,快递单号,发货时间\nB00001,顺丰,35434353,2025/8/11\nB00002,圆通,12345678,2025/8/11';
// 创建Blob对象添加BOM确保中文正常显示
const blob = new Blob(['\uFEFF' + csvContent], { type: 'text/csv;charset=utf-8' });
// 创建下载链接
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = '批量发货模板.csv';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
// 释放URL对象
URL.revokeObjectURL(link.href);
},
/** 刷新订单列表 */
refreshOrderList() {
this.getList();
},
/** 查看订单详情 */
async handleViewDetails(row) {
this.currentDetailOrder = row;
this.currentDetailOrderId = row.id; // 设置当前订单ID
this.detailDialogVisible = true;
},
/** 获取状态标签类型 */
getStatusTagType(status) {
const typeMap = {
1: 'info', // 待支付
2: 'success', // 已支付,待发货
3: 'warning', // 待收货
4: 'primary', // 待评价
5: 'success', // 已收货
6: 'danger', // 取消
20: 'warning', // 申请退款
21: 'success', // 同意退款
22: 'danger' // 驳回退款
};
return typeMap[status] || 'info';
},
/** 获取状态文本 */
getStatusText(status) {
const textMap = {
1: '待支付',
2: '已支付,待发货',
3: '待收货',
4: '待评价',
5: '已收货',
6: '已取消',
20: '申请退款',
21: '同意退款',
22: '驳回退款'
};
return textMap[status] || '未知状态';
},
/** 导出数据 */
handleExportData() {
this.$modal.confirm('确定要导出当前筛选条件下的订单数据吗?').then(() => {
// 这里可以调用导出API
this.$modal.msgSuccess('数据导出成功');
}).catch(() => {});
},
/** 切换高级搜索 */
toggleAdvancedSearch() {
this.showAdvancedSearch = !this.showAdvancedSearch;
},
fetchGoodsDataList() {
getGoodsDataList(2).then(response => {
this.goodsDataList = response.data;
});
},
getdeliveryList(){
getSiteDeliveryList().then(response => {
this.deliveryList = response.data;
});
},
/** 售后详情对话框关闭 */
handleAfterSaleClose() {
this.afterSaleDialogVisible = false;
// 使用nextTick确保弹窗完全关闭后再重置数据
this.$nextTick(() => {
this.currentAfterSaleOrder = null;
// 重置售后相关表单
this.rejectReasonForm.rejectReason = '';
this.refundAmountForm.returnrealmoney = '';
this.refundAmountForm.refundRemark = '';
});
},
/** 发货对话框关闭 */
handleShipClose() {
this.shipDialogVisible = false;
// 使用nextTick确保弹窗完全关闭后再重置数据
this.$nextTick(() => {
this.currentShipOrder = null;
this.shipmentOrders = [];
this.shipForm = {
id: null,
orderId: '',
productName: '',
name: '',
phone: '',
address: '',
deliveryId: null,
deliveryNum: '',
sendTime: '',
mark: ''
};
// 重置发货加载状态
this.shipLoading = false;
});
},
/** 预支付数据对话框关闭 */
handlePrePaymentClose() {
this.prePaymentDialogVisible = false;
// 使用nextTick确保弹窗完全关闭后再重置数据
this.$nextTick(() => {
this.prePaymentData = null;
});
},
/** 统一退款对话框关闭 */
handleUnifiedRefundClose() {
this.unifiedRefundDialogVisible = false;
this.currentRefundOrder = null;
this.currentRefundPaymentData = null;
},
/** 处理统一退款成功 */
handleRefundSuccess() {
this.unifiedRefundDialogVisible = false;
this.currentRefundOrder = null;
this.currentRefundPaymentData = null;
this.getList(); // 刷新列表
},
/** 统一退款按钮操作 */
handleUnifiedRefund(row) {
this.currentRefundOrder = row;
this.currentRefundPaymentData = {
wxmoney: row.payPrice || 0,
yemoney: 0,
shopmoney: 0,
servicemoney: 0,
membermoney: 0,
couponmoney: 0
};
this.unifiedRefundDialogVisible = true;
}
}
}
</script>
<style scoped>
/* 基本样式 */
.el-input__inner,
.el-select .el-input__inner,
.el-date-editor .el-input__inner,
.el-input-number .el-input__inner {
font-size: 16px !important;
color: #222 !important;
}
.el-form-item__label {
font-size: 16px !important;
color: #1a1a1a !important;
font-weight: bold;
}
.el-table th, .el-table td {
font-size: 16px !important;
color: #222 !important;
}
/* 表格行样式 */
::v-deep .main-order-row {
background-color: #f0f9ff !important;
font-weight: bold;
}
::v-deep .after-sale-pending-row {
background-color: #e7d9c9 !important;
color: #f56c6c !important;
}
::v-deep .order-paid-row {
background-color: #c7c3c3 !important;
color: #230cdb !important;
}
/* 商品相关样式 */
.product-summary {
text-align: center;
}
.product-preview {
margin-top: 8px;
}
.single-product {
text-align: center;
}
.product-image .image-slot {
display: flex;
justify-content: center;
align-items: center;
width: 50px;
height: 50px;
background: #f5f7fa;
color: #909399;
font-size: 20px;
}
.action-buttons {
display: flex;
gap: 10px;
margin-bottom: 15px;
}
.action-buttons .el-button {
flex: 1;
max-width: 120px;
}
.dialog-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
/* 高级搜索表单样式 */
.advanced-search-form {
background-color: #f8f9fa;
padding: 15px;
border-radius: 4px;
margin-bottom: 15px;
border: 1px solid #e9ecef;
}
.advanced-search-form .el-form-item {
margin-bottom: 10px;
margin-right: 15px;
}
/* 主订单行样式 */
.main-order-row {
background-color: #f8f9fa !important;
font-weight: 500;
}
.main-order-row:hover {
background-color: #e9ecef !important;
}
/* 商品汇总样式 */
.product-summary {
text-align: center;
padding: 8px;
}
.summary-header {
margin-bottom: 8px;
}
.order-counts {
margin-bottom: 8px;
}
.product-preview {
margin-top: 8px;
}
.single-product {
text-align: center;
padding: 8px;
}
/* 展开行样式 */
.expanded-content {
background-color: #fafafa;
border-radius: 4px;
}
.info-item .value.price {
color: #E6A23C;
font-weight: bold;
font-size: 16px;
}
.info-item .value.address {
word-break: break-all;
line-height: 1.4;
}
.stat-item {
text-align: center;
padding: 15px;
}
.stat-number {
font-size: 24px;
font-weight: bold;
color: #409EFF;
margin-bottom: 5px;
}
.stat-label {
color: #606266;
font-size: 14px;
}
.product-name {
display: flex;
align-items: center;
flex-wrap: wrap;
}
.product-name .name {
font-weight: 500;
margin-right: 8px;
}
.product-image {
text-align: center;
}
.image-slot {
display: flex;
justify-content: center;
align-items: center;
width: 50px;
height: 50px;
background: #f5f7fa;
color: #909399;
font-size: 20px;
}
/* 汇总项样式 */
.summary-item {
margin-bottom: 15px;
display: flex;
align-items: center;
}
.summary-item label {
font-weight: bold;
color: #606266;
min-width: 100px;
margin-right: 10px;
}
.summary-item .value {
color: #303133;
font-weight: 500;
}
.summary-item .value.highlight {
color: #409EFF;
font-weight: bold;
font-size: 18px;
}
.summary-item .value.price {
color: #E6A23C;
font-weight: bold;
font-size: 18px;
}
/* 价格样式 */
.price {
color: #E6A23C;
font-weight: 500;
}
.price.total {
font-weight: bold;
font-size: 14px;
}
/* 金额信息样式 */
.amount-total {
color: #E6A23C;
font-weight: bold;
font-size: 14px;
}
.amount-pay {
color: #409EFF;
font-weight: bold;
font-size: 14px;
}
.amount-deduction {
color: #F56C6C;
font-weight: bold;
font-size: 14px;
}
/* 表格列分组样式 */
.el-table th {
background-color: #f5f7fa;
color: #606266;
font-weight: 600;
}
/* 金额列样式 */
.el-table .el-table__cell.amount-column {
background-color: #fafafa;
}
/* 订单信息列样式 */
.el-table .el-table__cell.order-column {
background-color: #f0f9ff;
}
/* 商品信息列样式 */
.el-table .el-table__cell.product-column {
background-color: #f0f8f0;
}
/* 用户信息列样式 */
.el-table .el-table__cell.user-column {
background-color: #fff8f0;
}
/* 时间信息列样式 */
.el-table .el-table__cell.time-column {
background-color: #f8f0f8;
}
/* 表格头部样式优化 */
.el-table thead th {
background: linear-gradient(135deg, #f5f7fa 0%, #e4e7ed 100%);
border-bottom: 2px solid #dcdfe6;
font-weight: 600;
color: #303133;
}
/* 表格行悬停效果 */
.el-table tbody tr:hover > td {
background-color: #f5f7fa !important;
}
/* 响应式设计 */
@media (max-width: 1200px) {
.el-table .el-table__cell {
padding: 8px 4px;
}
.el-table th {
padding: 10px 4px;
}
}
@media (max-width: 768px) {
.el-table {
font-size: 12px;
}
.el-table .el-table__cell {
padding: 6px 2px;
}
.el-table th {
padding: 8px 2px;
}
}
/* 金额信息突出显示 */
.amount-total, .amount-pay, .amount-deduction {
padding: 2px 6px;
border-radius: 3px;
display: inline-block;
min-width: 60px;
text-align: center;
}
.amount-total {
background-color: #fdf6ec;
border: 1px solid #f5dab1;
}
.amount-pay {
background-color: #f0f9ff;
border: 1px solid #b3d8ff;
}
.amount-deduction {
background-color: #fef0f0;
border: 1px solid #fbc4c4;
}
/* 售后相关行样式 */
.after-sale-pending-row {
background-color: #fef0f0 !important;
}
.order-paid-row {
background-color: #f0f9ff !important;
}
.product-name .name {
font-weight: 500;
margin-right: 8px;
}
.product-description {
margin-top: 5px;
color: #909399;
font-size: 12px;
line-height: 1.4;
max-width: 300px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.product-image {
text-align: center;
}
</style>