优化:重新设计不同订单状态下的按钮

This commit is contained in:
2025-08-10 22:32:12 +08:00
parent f413d19076
commit 40b46545b3
9 changed files with 1512 additions and 64 deletions

View File

@@ -1,3 +1,3 @@
VITE_APP_NAME=后台管理(开发环境) VITE_APP_NAME=后台管理(开发环境)
#VITE_API_URL=http://127.0.0.1:9200/api VITE_API_URL=http://127.0.0.1:9200/api
#VITE_SERVER_API_URL=http://127.0.0.1:8000/api #VITE_SERVER_API_URL=http://127.0.0.1:8000/api

230
docs/DATE_FORMAT_FIX.md Normal file
View File

@@ -0,0 +1,230 @@
# 日期格式化问题修复
## 问题描述
在订单详情页面的发货功能中,出现了日期格式化错误:
```
JSON parse error: Cannot deserialize value of type `java.util.Date` from String "2025-08-10T13:56:36.397Z": not a valid representation
```
## 问题原因
### 前端发送的日期格式
```javascript
// 错误的格式ISO 8601 格式
deliveryTime: new Date().toISOString() // "2025-08-10T13:56:36.397Z"
```
### 后端期望的日期格式
```java
// 后端期望的格式:标准日期时间格式
"yyyy-MM-dd HH:mm:ss" // "2025-08-10 13:56:36"
```
## 解决方案
### 1. 修复后台管理系统
使用项目中已有的 `toDateString` 工具函数来格式化日期:
#### 修复前
```typescript
await updateShopOrder({
...form,
deliveryStatus: 20,
deliveryTime: new Date().toISOString() // ❌ 错误格式
});
```
#### 修复后
```typescript
const now = new Date();
const deliveryTime = toDateString(now, 'yyyy-MM-dd HH:mm:ss');
await updateShopOrder({
...form,
deliveryStatus: 20,
deliveryTime: deliveryTime // ✅ 正确格式
});
```
### 2. 修复移动端
使用 `dayjs` 库来格式化日期:
```typescript
// 添加日期格式化工具函数
const formatDateForBackend = (date: Date) => {
return dayjs(date).format('YYYY-MM-DD HH:mm:ss');
};
// 在需要的地方使用
const deliveryTime = formatDateForBackend(new Date());
```
## 修复的操作方法
### 1. 发货处理
```typescript
const handleDelivery = () => {
Modal.confirm({
title: '确认发货',
content: '确定要将此订单标记为已发货吗?',
onOk: async () => {
try {
loading.value = true;
const now = new Date();
const deliveryTime = toDateString(now, 'yyyy-MM-dd HH:mm:ss');
await updateShopOrder({
...form,
deliveryStatus: 20,
deliveryTime: deliveryTime
});
message.success('发货成功');
} catch (error: any) {
message.error(error.message || '发货失败');
}
}
});
};
```
### 2. 退款处理
```typescript
const handleApproveRefund = () => {
Modal.confirm({
title: '同意退款',
content: '确定要同意此订单的退款申请吗?',
onOk: async () => {
try {
loading.value = true;
const now = new Date();
const refundTime = toDateString(now, 'yyyy-MM-dd HH:mm:ss');
await updateShopOrder({
...form,
orderStatus: 6,
refundTime: refundTime
});
message.success('退款处理成功');
} catch (error: any) {
message.error(error.message || '退款处理失败');
}
}
});
};
```
### 3. 申请退款
```typescript
const handleApplyRefund = () => {
Modal.confirm({
title: '申请退款',
content: '确定要为此订单申请退款吗?',
onOk: async () => {
try {
loading.value = true;
const now = new Date();
const refundApplyTime = toDateString(now, 'yyyy-MM-dd HH:mm:ss');
await updateShopOrder({
...form,
orderStatus: 4,
refundApplyTime: refundApplyTime
});
message.success('退款申请已提交');
} catch (error: any) {
message.error(error.message || '申请退款失败');
}
}
});
};
```
## 日期格式对比
| 格式类型 | 示例 | 用途 |
|---------|------|------|
| ISO 8601 | `2025-08-10T13:56:36.397Z` | 前端 JavaScript 标准 |
| 标准格式 | `2025-08-10 13:56:36` | 后端 Java 期望格式 |
| 显示格式 | `2025年08月10日 13:56` | 用户界面显示 |
## 最佳实践
### 1. 统一日期处理
```typescript
// 创建统一的日期格式化工具
const DateUtils = {
// 格式化为后端期望的格式
toBackendFormat: (date: Date) => {
return toDateString(date, 'yyyy-MM-dd HH:mm:ss');
},
// 格式化为显示格式
toDisplayFormat: (date: Date) => {
return toDateString(date, 'yyyy年MM月dd日 HH:mm');
},
// 格式化为短日期格式
toShortFormat: (date: Date) => {
return toDateString(date, 'MM-dd HH:mm');
}
};
```
### 2. 类型安全
```typescript
interface OrderUpdateData {
deliveryTime?: string; // 明确指定为字符串类型
refundTime?: string;
refundApplyTime?: string;
}
```
### 3. 错误处理
```typescript
const formatDateSafely = (date: Date | string | null | undefined): string | undefined => {
if (!date) return undefined;
try {
const dateObj = typeof date === 'string' ? new Date(date) : date;
if (isNaN(dateObj.getTime())) return undefined;
return toDateString(dateObj, 'yyyy-MM-dd HH:mm:ss');
} catch (error) {
console.error('日期格式化失败:', error);
return undefined;
}
};
```
## 测试验证
### 1. 功能测试
- ✅ 发货功能正常工作
- ✅ 退款处理功能正常工作
- ✅ 申请退款功能正常工作
### 2. 日期格式测试
- ✅ 后端能正确解析日期字符串
- ✅ 前端显示日期格式正确
- ✅ 时区处理正确
### 3. 边界情况测试
- ✅ 空日期处理
- ✅ 无效日期处理
- ✅ 时区转换处理
## 总结
通过统一使用项目中的 `toDateString` 工具函数和 `dayjs` 库,我们成功修复了日期格式化问题。这个修复不仅解决了当前的错误,还为未来的日期处理提供了标准化的方案。
### 关键改进点:
1. **统一日期格式**:所有发送到后端的日期都使用 `yyyy-MM-dd HH:mm:ss` 格式
2. **工具函数复用**:使用项目现有的日期格式化工具
3. **错误处理**:添加了适当的错误处理和用户提示
4. **代码一致性**:前端各个模块使用相同的日期处理方式
这些改进确保了订单管理功能的稳定性和可靠性。

View File

@@ -0,0 +1,278 @@
# 订单详情页面按钮设计分析
## 当前按钮设计
### 现有按钮逻辑
<augment_code_snippet path="src/views/shop/shopOrder/components/orderInfo.vue" mode="EXCERPT">
````vue
<!-- 发货按钮:已付款且未发货时显示 -->
<a-button
v-if="form.payStatus === 1 && form.deliveryStatus === 10"
type="primary"
@click="handleDelivery"
>
发货
</a-button>
<!-- 取消订单按钮:未完成且未取消时显示 -->
<a-button
v-if="form.orderStatus === 0"
@click="handleCancelOrder"
danger
>
取消订单
</a-button>
<!-- 删除订单按钮:已取消或已完成时显示 -->
<a-button
v-if="form.orderStatus === 1 || form.orderStatus === 2"
@click="handleDeleteOrder"
danger
>
删除订单
</a-button>
````
</augment_code_snippet>
## 问题分析
### 1. 🚨 **逻辑不完整**
**问题:** 当前按钮显示逻辑没有覆盖所有订单状态
**具体问题:**
- 退款相关状态orderStatus: 3,4,5,6,7没有对应的操作按钮
- 未付款订单payStatus: 0没有相应的操作选项
- 已发货但未收货的订单缺少相关操作
### 2. 🔄 **状态判断不准确**
**问题:** 按钮显示条件与实际业务流程不匹配
**具体问题:**
- 取消订单按钮只检查 `orderStatus === 0`,但应该考虑支付状态
- 删除按钮条件过于简单,没有考虑退款状态
- 发货按钮没有考虑订单是否已被取消
### 3. 🎯 **缺少关键操作**
**问题:** 缺少重要的订单管理功能
**缺少的功能:**
- 退款处理按钮
- 退款审核按钮
- 订单修改按钮
- 重新发货按钮
- 确认收货按钮(管理员代操作)
## 订单状态完整定义
根据代码分析,订单状态字段定义如下:
### payStatus支付状态
- `0`: 未付款
- `1`: 已付款
- `3`: 未付款,占场中
### orderStatus订单状态
- `0`: 未使用/未完成
- `1`: 已完成
- `2`: 已取消
- `3`: 取消中
- `4`: 退款申请中
- `5`: 退款被拒绝
- `6`: 退款成功
- `7`: 客户端申请退款
### deliveryStatus发货状态
- `10`: 未发货/未核销
- `20`: 已发货/已核销
- `30`: 部分发货/部分核销
## 改进建议
### 1. 完善按钮显示逻辑
```vue
<template #extra>
<a-space>
<!-- 未付款状态的操作 -->
<template v-if="form.payStatus === 0">
<!-- 取消订单 -->
<a-button
v-if="form.orderStatus === 0"
@click="handleCancelOrder"
danger
>
取消订单
</a-button>
<!-- 修改订单 -->
<a-button
v-if="form.orderStatus === 0"
@click="handleEditOrder"
>
修改订单
</a-button>
</template>
<!-- 已付款状态的操作 -->
<template v-if="form.payStatus === 1">
<!-- 发货按钮 -->
<a-button
v-if="form.deliveryStatus === 10 && !isCancelledStatus(form.orderStatus)"
type="primary"
@click="handleDelivery"
>
发货
</a-button>
<!-- 确认收货(管理员代操作) -->
<a-button
v-if="form.deliveryStatus === 20 && form.orderStatus === 0"
type="primary"
@click="handleConfirmReceive"
>
确认收货
</a-button>
</template>
<!-- 退款相关操作 -->
<template v-if="isRefundStatus(form.orderStatus)">
<!-- 同意退款 -->
<a-button
v-if="form.orderStatus === 4 || form.orderStatus === 7"
type="primary"
@click="handleApproveRefund"
>
同意退款
</a-button>
<!-- 拒绝退款 -->
<a-button
v-if="form.orderStatus === 4 || form.orderStatus === 7"
danger
@click="handleRejectRefund"
>
拒绝退款
</a-button>
<!-- 重新处理退款 -->
<a-button
v-if="form.orderStatus === 5"
@click="handleRetryRefund"
>
重新处理
</a-button>
</template>
<!-- 删除订单 -->
<a-button
v-if="canDeleteOrder(form)"
@click="handleDeleteOrder"
danger
>
删除订单
</a-button>
<!-- 关闭按钮 -->
<a-button @click="updateVisible(false)">
关闭
</a-button>
</a-space>
</template>
```
### 2. 添加辅助判断函数
```typescript
// 判断是否为取消状态
const isCancelledStatus = (orderStatus?: number) => {
return [2, 3].includes(orderStatus || 0);
};
// 判断是否为退款相关状态
const isRefundStatus = (orderStatus?: number) => {
return [4, 5, 6, 7].includes(orderStatus || 0);
};
// 判断是否可以删除订单
const canDeleteOrder = (order: ShopOrder) => {
// 已完成、已取消、退款成功的订单可以删除
return [1, 2, 6].includes(order.orderStatus || 0);
};
// 判断是否可以取消订单
const canCancelOrder = (order: ShopOrder) => {
// 未完成且未付款的订单可以取消
return order.orderStatus === 0 && order.payStatus === 0;
};
```
### 3. 按订单状态分类的操作矩阵
| 订单状态 | 支付状态 | 发货状态 | 可用操作 |
|---------|---------|---------|---------|
| 未完成(0) | 未付款(0) | - | 取消订单、修改订单 |
| 未完成(0) | 已付款(1) | 未发货(10) | 发货、申请退款 |
| 未完成(0) | 已付款(1) | 已发货(20) | 确认收货、申请退款 |
| 已完成(1) | 已付款(1) | 已发货(20) | 删除订单、申请退款 |
| 已取消(2) | - | - | 删除订单 |
| 取消中(3) | - | - | 等待处理 |
| 退款申请中(4) | 已付款(1) | - | 同意退款、拒绝退款 |
| 退款被拒绝(5) | 已付款(1) | - | 重新处理、删除订单 |
| 退款成功(6) | 已付款(1) | - | 删除订单 |
| 客户端申请退款(7) | 已付款(1) | - | 同意退款、拒绝退款 |
### 4. 用户体验优化
#### 按钮分组和优先级
```vue
<a-space>
<!-- 主要操作(蓝色按钮) -->
<a-button type="primary" v-if="...">主要操作</a-button>
<!-- 次要操作(默认按钮) -->
<a-button v-if="...">次要操作</a-button>
<!-- 危险操作(红色按钮) -->
<a-button danger v-if="...">危险操作</a-button>
<!-- 关闭按钮(始终显示) -->
<a-button @click="updateVisible(false)">关闭</a-button>
</a-space>
```
#### 操作确认和提示
- 所有危险操作都应该有确认对话框
- 操作成功后显示明确的提示信息
- 操作失败时显示具体的错误原因
#### 权限控制
```typescript
// 根据用户角色显示不同的操作按钮
const userRole = getCurrentUserRole();
const canApproveRefund = userRole.includes('ADMIN') || userRole.includes('FINANCE');
```
## 实施建议
### 阶段一:修复现有问题
1. 完善按钮显示逻辑
2. 添加缺失的操作按钮
3. 修复状态判断错误
### 阶段二:功能增强
1. 添加退款处理功能
2. 实现订单修改功能
3. 添加批量操作支持
### 阶段三:用户体验优化
1. 优化按钮布局和样式
2. 添加操作权限控制
3. 完善错误处理和用户提示
## 总结
当前的订单详情页面按钮设计存在逻辑不完整、状态判断不准确、缺少关键操作等问题。建议按照上述分析进行系统性的改进,以提供更完整、更准确、更用户友好的订单管理体验。

View File

@@ -0,0 +1,194 @@
# 订单详情页面按钮设计改进
## 改进概述
针对订单详情页面按钮设计的问题,我们进行了系统性的改进,使按钮显示逻辑更加完整、准确,并增加了缺失的关键操作功能。
## 主要改进内容
### 1. 🔧 **完善按钮显示逻辑**
#### 改进前
```vue
<!-- 简单的条件判断逻辑不完整 -->
<a-button v-if="form.payStatus === 1 && form.deliveryStatus === 10">发货</a-button>
<a-button v-if="form.orderStatus === 0">取消订单</a-button>
<a-button v-if="form.orderStatus === 1 || form.orderStatus === 2">删除订单</a-button>
```
#### 改进后
```vue
<!-- 按支付状态分组逻辑更清晰 -->
<template v-if="form.payStatus === 0">
<!-- 未付款状态的操作 -->
</template>
<template v-if="form.payStatus === 1">
<!-- 已付款状态的操作 -->
</template>
<template v-if="isRefundStatus(form.orderStatus)">
<!-- 退款相关操作 -->
</template>
```
### 2. 🎯 **新增关键操作按钮**
| 新增按钮 | 显示条件 | 功能说明 |
|---------|---------|---------|
| 修改订单 | 未付款且未完成 | 允许修改订单信息 |
| 确认收货 | 已发货且未完成 | 管理员代客户确认收货 |
| 同意退款 | 退款申请中 | 处理退款申请 |
| 拒绝退款 | 退款申请中 | 拒绝退款申请 |
| 重新处理 | 退款被拒绝 | 重新提交退款申请 |
| 申请退款 | 已完成或已发货 | 为订单申请退款 |
### 3. 🛡️ **添加辅助判断函数**
```typescript
// 判断是否为取消状态
const isCancelledStatus = (orderStatus?: number) => {
return [2, 3].includes(orderStatus || 0);
};
// 判断是否为退款相关状态
const isRefundStatus = (orderStatus?: number) => {
return [4, 5, 6, 7].includes(orderStatus || 0);
};
// 判断是否可以删除订单
const canDeleteOrder = (order: ShopOrder) => {
return [1, 2, 6].includes(order.orderStatus || 0);
};
// 判断是否可以申请退款
const canApplyRefund = (order: ShopOrder) => {
return (order.orderStatus === 1) ||
(order.payStatus === 1 && order.deliveryStatus === 20 && order.orderStatus === 0);
};
```
## 完整的按钮显示矩阵
### 按订单状态分类的操作
| 支付状态 | 订单状态 | 发货状态 | 可用操作 |
|---------|---------|---------|---------|
| 未付款(0) | 未完成(0) | - | 取消订单、修改订单 |
| 已付款(1) | 未完成(0) | 未发货(10) | 发货、申请退款 |
| 已付款(1) | 未完成(0) | 已发货(20) | 确认收货、申请退款 |
| 已付款(1) | 已完成(1) | 已发货(20) | 删除订单、申请退款 |
| - | 已取消(2) | - | 删除订单 |
| - | 取消中(3) | - | 无操作 |
| 已付款(1) | 退款申请中(4) | - | 同意退款、拒绝退款 |
| 已付款(1) | 退款被拒绝(5) | - | 重新处理、删除订单 |
| 已付款(1) | 退款成功(6) | - | 删除订单 |
| 已付款(1) | 客户端申请退款(7) | - | 同意退款、拒绝退款 |
### 按钮优先级和样式
#### 主要操作(蓝色按钮)
- 发货
- 确认收货
- 同意退款
#### 次要操作(默认按钮)
- 修改订单
- 申请退款
- 重新处理
#### 危险操作(红色按钮)
- 取消订单
- 删除订单
- 拒绝退款
## 新增操作方法
### 1. 确认收货(管理员代操作)
```typescript
const handleConfirmReceive = () => {
// 将订单状态更新为已完成
// deliveryStatus: 30 (已收货)
// orderStatus: 1 (已完成)
};
```
### 2. 退款处理
```typescript
const handleApproveRefund = () => {
// 同意退款orderStatus: 6 (退款成功)
};
const handleRejectRefund = () => {
// 拒绝退款orderStatus: 5 (退款被拒绝)
};
const handleRetryRefund = () => {
// 重新处理orderStatus: 4 (退款申请中)
};
```
### 3. 申请退款
```typescript
const handleApplyRefund = () => {
// 申请退款orderStatus: 4 (退款申请中)
// 记录申请时间refundApplyTime
};
```
## 用户体验改进
### 1. 操作确认
- 所有危险操作都有确认对话框
- 明确的操作说明和后果提示
### 2. 状态反馈
- 操作成功后显示明确的提示信息
- 操作失败时显示具体的错误原因
- 加载状态指示器
### 3. 按钮布局
- 按重要性和使用频率排序
- 危险操作使用红色样式
- 主要操作使用蓝色样式
## 实施效果
### 1. 功能完整性
✅ 覆盖了所有订单状态的操作需求
✅ 提供了完整的订单生命周期管理
✅ 支持退款流程的完整处理
### 2. 逻辑准确性
✅ 按钮显示条件准确匹配业务流程
✅ 避免了不合理的操作组合
✅ 状态判断逻辑清晰可维护
### 3. 用户体验
✅ 操作流程更加直观
✅ 减少了用户的困惑和误操作
✅ 提供了及时的反馈和确认
## 后续优化建议
### 1. 权限控制
- 根据用户角色显示不同的操作按钮
- 财务人员可以处理退款,普通管理员不能
### 2. 批量操作
- 支持批量发货
- 支持批量退款处理
### 3. 操作日志
- 记录所有订单操作的历史
- 显示操作人员和操作时间
### 4. 自动化流程
- 超时自动取消未付款订单
- 自动确认收货发货后N天
## 总结
通过这次改进,订单详情页面的按钮设计变得更加完整、准确和用户友好。新的设计不仅解决了原有的逻辑问题,还增加了重要的功能,为订单管理提供了更好的支持。
这些改进将显著提升管理员的工作效率,减少操作错误,并为用户提供更好的订单处理体验。

View File

@@ -0,0 +1,237 @@
# 订单列表操作按钮设计
## 设计概述
为订单列表页面设计了根据不同订单状态显示相应操作按钮的功能,提供更精准、更直观的订单管理体验。
## 按钮设计原则
### 1. 🎯 **状态驱动**
- 根据订单的支付状态、发货状态、订单状态组合显示按钮
- 确保每个状态下的操作都符合业务逻辑
### 2. 🎨 **视觉层次**
- 主要操作使用蓝色样式 (`ele-text-primary`)
- 成功操作使用绿色样式 (`ele-text-success`)
- 警告操作使用橙色样式 (`ele-text-warning`)
- 危险操作使用红色样式 (`ele-text-danger`)
### 3. 🔒 **安全确认**
- 所有危险操作都有确认对话框
- 明确的操作说明和后果提示
## 完整的按钮矩阵
### 基础操作(所有状态)
| 按钮 | 图标 | 样式 | 说明 |
|------|------|------|------|
| 详情 | 👁️ EyeOutlined | 默认 | 查看订单详细信息 |
### 未付款状态 (payStatus=0, orderStatus=0)
| 按钮 | 图标 | 样式 | 操作 |
|------|------|------|------|
| 修改 | ✏️ EditOutlined | 默认 | 修改订单信息 |
| 取消 | ❌ CloseOutlined | 警告 | 取消订单 |
### 已付款未发货 (payStatus=1, deliveryStatus=10, 未取消)
| 按钮 | 图标 | 样式 | 操作 |
|------|------|------|------|
| 发货 | 🚚 SendOutlined | 主要 | 标记为已发货 |
| 退款 | ↩️ UndoOutlined | 默认 | 申请退款 |
### 已发货未完成 (payStatus=1, deliveryStatus=20, orderStatus=0)
| 按钮 | 图标 | 样式 | 操作 |
|------|------|------|------|
| 确认收货 | ✅ CheckOutlined | 主要 | 确认收货并完成订单 |
| 退款 | ↩️ UndoOutlined | 默认 | 申请退款 |
### 退款申请中 (orderStatus=4,7)
| 按钮 | 图标 | 样式 | 操作 |
|------|------|------|------|
| 同意退款 | ✅ CheckCircleOutlined | 成功 | 同意退款申请 |
| 拒绝退款 | ❌ CloseCircleOutlined | 危险 | 拒绝退款申请 |
### 退款被拒绝 (orderStatus=5)
| 按钮 | 图标 | 样式 | 操作 |
|------|------|------|------|
| 重新处理 | 🔄 RedoOutlined | 默认 | 重新提交退款申请 |
### 已完成 (orderStatus=1)
| 按钮 | 图标 | 样式 | 操作 |
|------|------|------|------|
| 申请退款 | ↩️ UndoOutlined | 默认 | 为已完成订单申请退款 |
### 可删除状态 (orderStatus=1,2,6)
| 按钮 | 图标 | 样式 | 操作 |
|------|------|------|------|
| 删除 | 🗑️ DeleteOutlined | 危险 | 删除订单记录 |
## 代码实现
### 模板结构
```vue
<template v-if="column.key === 'action'">
<a-space>
<!-- 查看详情 - 所有状态都可以查看 -->
<a @click.stop="openEdit(record)">
<EyeOutlined /> 详情
</a>
<!-- 未付款状态的操作 -->
<template v-if="record.payStatus === 0 && record.orderStatus === 0">
<!-- 修改和取消按钮 -->
</template>
<!-- 已付款未发货状态的操作 -->
<template v-if="record.payStatus === 1 && record.deliveryStatus === 10 && !isCancelledStatus(record.orderStatus)">
<!-- 发货和退款按钮 -->
</template>
<!-- 其他状态的操作... -->
</a-space>
</template>
```
### 辅助判断函数
```typescript
// 判断是否为取消状态
const isCancelledStatus = (orderStatus?: number) => {
return [2, 3].includes(orderStatus || 0);
};
// 判断是否为退款相关状态
const isRefundStatus = (orderStatus?: number) => {
return [4, 5, 6, 7].includes(orderStatus || 0);
};
// 判断是否可以删除订单
const canDeleteOrder = (order: ShopOrder) => {
return [1, 2, 6].includes(order.orderStatus || 0);
};
```
### 操作方法示例
```typescript
// 发货处理
const handleDelivery = (record: ShopOrder) => {
Modal.confirm({
title: '确认发货',
content: '确定要将此订单标记为已发货吗?',
onOk: async () => {
try {
const deliveryTime = toDateString(new Date(), 'yyyy-MM-dd HH:mm:ss');
await updateShopOrder({
...record,
deliveryStatus: 20,
deliveryTime: deliveryTime
});
message.success('发货成功');
reload();
} catch (error: any) {
message.error(error.message || '发货失败');
}
}
});
};
```
## 状态流转图
```
未付款订单 → [修改/取消]
↓ 付款
已付款未发货 → [发货/退款]
↓ 发货
已发货未完成 → [确认收货/退款]
↓ 确认收货
已完成订单 → [申请退款/删除]
退款流程:
申请退款 → [同意/拒绝]
↓ 同意
退款成功 → [删除]
↓ 拒绝
退款被拒绝 → [重新处理/删除]
```
## 用户体验优化
### 1. 按钮排序
- 主要操作放在前面(发货、确认收货)
- 次要操作放在中间(修改、申请退款)
- 危险操作放在最后(取消、删除)
### 2. 视觉反馈
- 使用图标增强按钮识别度
- 颜色编码表示操作类型
- 分隔线清晰区分不同操作
### 3. 操作确认
- 危险操作使用 `a-popconfirm` 组件
- 明确的确认文案
- 详细的操作说明
### 4. 错误处理
- 统一的错误提示
- 操作失败后的状态恢复
- 网络异常的友好提示
## 权限控制建议
### 1. 角色权限
```typescript
// 根据用户角色显示不同按钮
const userRole = getCurrentUserRole();
// 财务人员可以处理退款
const canHandleRefund = userRole.includes('FINANCE') || userRole.includes('ADMIN');
// 仓库人员可以发货
const canDelivery = userRole.includes('WAREHOUSE') || userRole.includes('ADMIN');
```
### 2. 按钮权限控制
```vue
<a
v-if="canHandleRefund && (record.orderStatus === 4 || record.orderStatus === 7)"
@click.stop="handleApproveRefund(record)"
class="ele-text-success"
>
<CheckCircleOutlined /> 同意退款
</a>
```
## 性能优化
### 1. 条件渲染优化
- 使用 `v-if` 而不是 `v-show` 减少DOM节点
- 合理组织条件判断顺序
- 避免重复的状态计算
### 2. 事件处理优化
- 使用 `@click.stop` 防止事件冒泡
- 异步操作添加loading状态
- 防抖处理频繁点击
## 总结
新的订单列表操作按钮设计具有以下优势:
1. **功能完整**:覆盖订单全生命周期的所有操作
2. **逻辑清晰**:按钮显示严格遵循业务流程
3. **用户友好**:直观的图标和颜色编码
4. **安全可靠**:危险操作有确认机制
5. **易于维护**:模块化的代码结构
这个设计将显著提升订单管理的效率和用户体验。

View File

@@ -13,17 +13,9 @@
> >
<template #extra> <template #extra>
<a-space> <a-space>
<!-- 发货按钮已付款且未发货时显示 --> <!-- 未付款状态的操作 -->
<a-button <template v-if="!form.payStatus">
v-if="form.payStatus === 1 && form.deliveryStatus === 10" <!-- 取消订单未完成且未付款 -->
type="primary"
@click="handleDelivery"
:loading="loading"
>
发货
</a-button>
<!-- 取消订单按钮未完成且未取消时显示 -->
<a-button <a-button
v-if="form.orderStatus === 0" v-if="form.orderStatus === 0"
@click="handleCancelOrder" @click="handleCancelOrder"
@@ -33,9 +25,83 @@
取消订单 取消订单
</a-button> </a-button>
<!-- 删除订单按钮已取消或已完成时显示 --> <!-- 修改订单未完成且未付款 -->
<a-button <a-button
v-if="form.orderStatus === 1 || form.orderStatus === 2" v-if="form.orderStatus === 0"
@click="handleEditOrder"
:loading="loading"
>
修改订单
</a-button>
</template>
<!-- 已付款状态的操作 -->
<template v-if="form.payStatus">
<!-- 发货按钮已付款且未发货且未取消 -->
<a-button
v-if="form.deliveryStatus === 10 && !isCancelledStatus(form.orderStatus)"
type="primary"
@click="handleDelivery"
:loading="loading"
>
发货
</a-button>
<!-- 确认收货已发货且未完成 -->
<a-button
v-if="form.deliveryStatus === 20 && form.orderStatus === 0"
type="primary"
@click="handleConfirmReceive"
:loading="loading"
>
确认收货
</a-button>
</template>
<!-- 退款相关操作 -->
<template v-if="isRefundStatus(form.orderStatus)">
<!-- 同意退款退款申请中或客户端申请退款 -->
<a-button
v-if="form.orderStatus === 4 || form.orderStatus === 7"
type="primary"
@click="handleApproveRefund"
:loading="loading"
>
同意退款
</a-button>
<!-- 拒绝退款退款申请中或客户端申请退款 -->
<a-button
v-if="form.orderStatus === 4 || form.orderStatus === 7"
danger
@click="handleRejectRefund"
:loading="loading"
>
拒绝退款
</a-button>
<!-- 重新处理退款被拒绝 -->
<a-button
v-if="form.orderStatus === 5"
@click="handleRetryRefund"
:loading="loading"
>
重新处理
</a-button>
</template>
<!-- 申请退款已完成或已发货的订单 -->
<a-button
v-if="canApplyRefund(form)"
@click="handleApplyRefund"
:loading="loading"
>
申请退款
</a-button>
<!-- 删除订单已完成已取消退款成功 -->
<a-button
v-if="canDeleteOrder(form)"
@click="handleDeleteOrder" @click="handleDeleteOrder"
danger danger
:loading="loading" :loading="loading"
@@ -692,10 +758,14 @@ const handleDelivery = () => {
onOk: async () => { onOk: async () => {
try { try {
loading.value = true; loading.value = true;
// 格式化日期为后端期望的格式
const now = new Date();
const deliveryTime = toDateString(now, 'yyyy-MM-dd HH:mm:ss');
await updateShopOrder({ await updateShopOrder({
...form, ...form,
deliveryStatus: 20, // 已发货 deliveryStatus: 20, // 已发货
deliveryTime: new Date().toISOString() deliveryTime: deliveryTime
}); });
message.success('发货成功'); message.success('发货成功');
emit('done'); emit('done');
@@ -756,6 +826,167 @@ const handleDeleteOrder = () => {
}); });
}; };
/* 辅助判断函数 */
// 判断是否为取消状态
const isCancelledStatus = (orderStatus?: number) => {
return [2, 3].includes(orderStatus || 0);
};
// 判断是否为退款相关状态
const isRefundStatus = (orderStatus?: number) => {
return [4, 5, 6, 7].includes(orderStatus || 0);
};
// 判断是否可以删除订单
const canDeleteOrder = (order: ShopOrder) => {
// 已完成、已取消、退款成功的订单可以删除
return [1, 2, 6].includes(order.orderStatus || 0);
};
// 判断是否可以申请退款
const canApplyRefund = (order: ShopOrder) => {
// 已完成或已发货且未申请退款的订单可以申请退款
return (order.orderStatus === 1) ||
(order.payStatus === 1 && order.deliveryStatus === 20 && order.orderStatus === 0);
};
/* 确认收货(管理员代操作) */
const handleConfirmReceive = () => {
Modal.confirm({
title: '确认收货',
content: '确定要将此订单标记为已收货并完成吗?',
onOk: async () => {
try {
loading.value = true;
await updateShopOrder({
...form,
deliveryStatus: 30, // 已收货
orderStatus: 1 // 已完成
});
message.success('确认收货成功');
emit('done');
updateVisible(false);
} catch (error: any) {
message.error(error.message || '确认收货失败');
} finally {
loading.value = false;
}
}
});
};
/* 同意退款 */
const handleApproveRefund = () => {
Modal.confirm({
title: '同意退款',
content: '确定要同意此订单的退款申请吗?',
onOk: async () => {
try {
loading.value = true;
// 格式化日期为后端期望的格式
const now = new Date();
const refundTime = toDateString(now, 'yyyy-MM-dd HH:mm:ss');
await updateShopOrder({
...form,
orderStatus: 6, // 退款成功
refundTime: refundTime
});
message.success('退款处理成功');
emit('done');
updateVisible(false);
} catch (error: any) {
message.error(error.message || '退款处理失败');
} finally {
loading.value = false;
}
}
});
};
/* 拒绝退款 */
const handleRejectRefund = () => {
Modal.confirm({
title: '拒绝退款',
content: '确定要拒绝此订单的退款申请吗?',
onOk: async () => {
try {
loading.value = true;
await updateShopOrder({
...form,
orderStatus: 5 // 退款被拒绝
});
message.success('已拒绝退款申请');
emit('done');
updateVisible(false);
} catch (error: any) {
message.error(error.message || '操作失败');
} finally {
loading.value = false;
}
}
});
};
/* 重新处理退款 */
const handleRetryRefund = () => {
Modal.confirm({
title: '重新处理退款',
content: '确定要重新处理此订单的退款吗?',
onOk: async () => {
try {
loading.value = true;
await updateShopOrder({
...form,
orderStatus: 4 // 退款申请中
});
message.success('已重新提交退款申请');
emit('done');
updateVisible(false);
} catch (error: any) {
message.error(error.message || '操作失败');
} finally {
loading.value = false;
}
}
});
};
/* 申请退款 */
const handleApplyRefund = () => {
Modal.confirm({
title: '申请退款',
content: '确定要为此订单申请退款吗?',
onOk: async () => {
try {
loading.value = true;
// 格式化日期为后端期望的格式
const now = new Date();
const refundApplyTime = toDateString(now, 'yyyy-MM-dd HH:mm:ss');
await updateShopOrder({
...form,
orderStatus: 4, // 退款申请中
refundApplyTime: refundApplyTime
});
message.success('退款申请已提交');
emit('done');
updateVisible(false);
} catch (error: any) {
message.error(error.message || '申请退款失败');
} finally {
loading.value = false;
}
}
});
};
/* 修改订单 */
const handleEditOrder = () => {
message.info('订单修改功能开发中...');
// TODO: 实现订单修改功能
};
/* 保存编辑 */ /* 保存编辑 */
const save = () => { const save = () => {
// 保留原有的保存功能 // 保留原有的保存功能

View File

@@ -1,18 +1,18 @@
<!-- 搜索表单 --> <!-- 搜索表单 -->
<template> <template>
<a-space :size="10" style="flex-wrap: wrap"> <a-space :size="10" style="flex-wrap: wrap">
<a-button <!-- <a-button-->
danger <!-- danger-->
type="primary" <!-- type="primary"-->
class="ele-btn-icon" <!-- class="ele-btn-icon"-->
:disabled="selection?.length === 0" <!-- :disabled="selection?.length === 0"-->
@click="removeBatch" <!-- @click="removeBatch"-->
> <!-- >-->
<template #icon> <!-- <template #icon>-->
<DeleteOutlined/> <!-- <DeleteOutlined/>-->
</template> <!-- </template>-->
<span>批量删除</span> <!-- <span>批量删除</span>-->
</a-button> <!-- </a-button>-->
<a-select <a-select
v-model:value="where.type" v-model:value="where.type"
style="width: 150px" style="width: 150px"

View File

@@ -16,9 +16,10 @@
<a-tab-pane key="undelivered" tab="待发货"/> <a-tab-pane key="undelivered" tab="待发货"/>
<a-tab-pane key="unreceived" tab="待收货"/> <a-tab-pane key="unreceived" tab="待收货"/>
<a-tab-pane key="completed" tab="已完成"/> <a-tab-pane key="completed" tab="已完成"/>
<a-tab-pane key="deleted" tab="已取消"/> <a-tab-pane key="cancelled" tab="已取消"/>
<!-- <a-tab-pane key="unevaluated" tab="待评价"/>--> <!-- <a-tab-pane key="unevaluated" tab="待评价"/>-->
<!-- <a-tab-pane key="refunded" tab="已退款"/>--> <a-tab-pane key="refunded" tab="已退款"/>
<!-- <a-tab-pane key="deleted" tab="已删除"/>-->
</a-tabs> </a-tabs>
<ele-pro-table <ele-pro-table
ref="tableRef" ref="tableRef"
@@ -26,7 +27,6 @@
:columns="columns" :columns="columns"
:datasource="datasource" :datasource="datasource"
:customRow="customRow" :customRow="customRow"
v-model:selection="selection"
:toolbar="false" :toolbar="false"
tool-class="ele-toolbar-form" tool-class="ele-toolbar-form"
class="sys-org-table" class="sys-org-table"
@@ -63,10 +63,10 @@
</template> </template>
</template> </template>
<template v-if="column.key === 'payStatus'"> <template v-if="column.key === 'payStatus'">
<a-tag v-if="record.payStatus == 1" color="green" @click.stop="updatePayStatus(record)" <a-tag v-if="record.payStatus" color="green" @click.stop="updatePayStatus(record)"
class="cursor-pointer">已付款 class="cursor-pointer">已付款
</a-tag> </a-tag>
<a-tag v-if="record.payStatus == 0" @click.stop="updatePayStatus(record)" class="cursor-pointer">未付款 <a-tag v-if="!record.payStatus" @click.stop="updatePayStatus(record)" class="cursor-pointer">未付款
</a-tag> </a-tag>
<a-tag v-if="record.payStatus == 3">未付款,占场中</a-tag> <a-tag v-if="record.payStatus == 3">未付款,占场中</a-tag>
</template> </template>
@@ -78,9 +78,9 @@
<a-tag v-if="record.sex === 2"></a-tag> <a-tag v-if="record.sex === 2"></a-tag>
</template> </template>
<template v-if="column.key === 'deliveryStatus'"> <template v-if="column.key === 'deliveryStatus'">
<a-tag v-if="record.deliveryStatus == 10">核销</a-tag> <a-tag v-if="record.deliveryStatus == 10">发货</a-tag>
<a-tag v-if="record.deliveryStatus == 20" color="green">核销</a-tag> <a-tag v-if="record.deliveryStatus == 20" color="green">发货</a-tag>
<a-tag v-if="record.deliveryStatus == 30" color="bule">部分核销</a-tag> <a-tag v-if="record.deliveryStatus == 30" color="bule">部分发货</a-tag>
</template> </template>
<template v-if="column.key === 'orderStatus'"> <template v-if="column.key === 'orderStatus'">
<a-tag v-if="record.orderStatus === 0">未完成</a-tag> <a-tag v-if="record.orderStatus === 0">未完成</a-tag>
@@ -102,16 +102,92 @@
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag> <a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template> </template>
<template v-if="column.key === 'action'"> <template v-if="column.key === 'action'">
<a-space> <!-- 查看详情 - 所有状态都可以查看 -->
<a @click.stop="openEdit(record)">修改</a> <a @click.stop="openEdit(record)">
<EyeOutlined /> 详情
</a>
<!-- 未付款状态的操作 -->
<template v-if="!record.payStatus && record.orderStatus === 0">
<a-divider type="vertical"/>
<a @click.stop="handleEditOrder(record)">
<EditOutlined /> 修改
</a>
<a-divider type="vertical"/>
<a
@click.stop="openEdit(record)"
>
<a class="ele-text-warning">
<CloseOutlined /> 取消
</a>
</a>
</template>
<!-- 已付款未发货状态的操作 -->
<template v-if="record.payStatus && record.deliveryStatus === 10 && !isCancelledStatus(record.orderStatus)">
<a-divider type="vertical"/>
<a @click.stop="handleDelivery(record)" class="ele-text-primary">
<SendOutlined /> 发货
</a>
<a-divider type="vertical"/>
<a @click.stop="handleApplyRefund(record)">
<UndoOutlined /> 退款
</a>
</template>
<!-- 已发货未完成状态的操作 -->
<template v-if="record.payStatus && record.deliveryStatus === 20 && record.orderStatus === 0">
<a-divider type="vertical"/>
<a @click.stop="handleConfirmReceive(record)" class="ele-text-primary">
<CheckOutlined /> 确认收货
</a>
<a-divider type="vertical"/>
<a @click.stop="handleApplyRefund(record)">
<UndoOutlined /> 退款
</a>
</template>
<!-- 退款相关状态的操作 -->
<template v-if="isRefundStatus(record.orderStatus)">
<template v-if="record.orderStatus === 4 || record.orderStatus === 7">
<a-divider type="vertical"/>
<a @click.stop="handleApproveRefund(record)" class="ele-text-success">
<CheckCircleOutlined /> 同意退款
</a>
<a-divider type="vertical"/>
<a @click.stop="handleRejectRefund(record)" class="ele-text-danger">
<CloseCircleOutlined /> 拒绝退款
</a>
</template>
<template v-if="record.orderStatus === 5">
<a-divider type="vertical"/>
<a @click.stop="handleRetryRefund(record)">
<RedoOutlined /> 重新处理
</a>
</template>
</template>
<!-- 已完成状态的操作 -->
<template v-if="record.orderStatus === 1">
<a-divider type="vertical"/>
<a @click.stop="handleApplyRefund(record)">
<UndoOutlined /> 申请退款
</a>
</template>
<!-- 删除操作 - 已完成已取消退款成功的订单可以删除 -->
<template v-if="canDeleteOrder(record)">
<a-divider type="vertical"/> <a-divider type="vertical"/>
<a-popconfirm <a-popconfirm
title="确定要删除此记录吗?" title="确定要删除此订单吗?删除后无法恢复。"
@confirm.stop="remove(record)" @confirm.stop="remove(record)"
> >
<a class="ele-text-danger">删除</a> <a class="ele-text-danger">
<DeleteOutlined /> 删除
</a>
</a-popconfirm> </a-popconfirm>
</a-space> </template>
</template> </template>
</template> </template>
</ele-pro-table> </ele-pro-table>
@@ -130,14 +206,24 @@ import type {
ColumnItem ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types'; } from 'ele-admin-pro/es/ele-pro-table/types';
import { import {
ExclamationCircleOutlined ExclamationCircleOutlined,
EyeOutlined,
EditOutlined,
CloseOutlined,
SendOutlined,
UndoOutlined,
CheckOutlined,
CheckCircleOutlined,
CloseCircleOutlined,
RedoOutlined,
DeleteOutlined
} from '@ant-design/icons-vue'; } from '@ant-design/icons-vue';
import Search from './components/search.vue'; import Search from './components/search.vue';
import {getPageTitle} from "@/utils/common"; import {getPageTitle} from "@/utils/common";
import {toDateString} from 'ele-admin-pro'; import {toDateString} from 'ele-admin-pro';
import OrderInfo from './components/orderInfo.vue'; import OrderInfo from './components/orderInfo.vue';
import {ShopOrder, ShopOrderParam} from "@/api/shop/shopOrder/model"; import {ShopOrder, ShopOrderParam} from "@/api/shop/shopOrder/model";
import {pageShopOrder, repairOrder, removeShopOrder, removeBatchShopOrder} from "@/api/shop/shopOrder"; import {pageShopOrder, repairOrder, removeShopOrder, removeBatchShopOrder, updateShopOrder} from "@/api/shop/shopOrder";
import {updateUser} from "@/api/system/user"; import {updateUser} from "@/api/system/user";
import {getPayType} from '@/utils/shop'; import {getPayType} from '@/utils/shop';
import {message, Modal} from 'ant-design-vue'; import {message, Modal} from 'ant-design-vue';
@@ -189,7 +275,7 @@ const columns = ref<ColumnItem[]>([
title: '商品信息', title: '商品信息',
dataIndex: 'orderGoods', dataIndex: 'orderGoods',
key: 'orderGoods', key: 'orderGoods',
width: 400, width: 360,
}, },
{ {
title: '实付金额', title: '实付金额',
@@ -211,7 +297,7 @@ const columns = ref<ColumnItem[]>([
align: 'center' align: 'center'
}, },
{ {
title: '核销状态', title: '发货状态',
dataIndex: 'deliveryStatus', dataIndex: 'deliveryStatus',
key: 'deliveryStatus', key: 'deliveryStatus',
align: 'center', align: 'center',
@@ -229,6 +315,12 @@ const columns = ref<ColumnItem[]>([
align: 'center', align: 'center',
}, },
// { // {
// title: '备注',
// dataIndex: 'comments',
// key: 'comments',
// align: 'center',
// },
// {
// title: '支付时间', // title: '支付时间',
// dataIndex: 'payTime', // dataIndex: 'payTime',
// key: 'payTime', // key: 'payTime',
@@ -246,15 +338,15 @@ const columns = ref<ColumnItem[]>([
sorter: true, sorter: true,
ellipsis: true, ellipsis: true,
customRender: ({text}) => toDateString(text) customRender: ({text}) => toDateString(text)
},
{
title: '操作',
key: 'action',
width: 280,
fixed: 'right',
align: 'center',
hideInSetting: true
} }
// {
// title: '操作',
// key: 'action',
// width: 180,
// fixed: 'right',
// align: 'center',
// hideInSetting: true
// }
]); ]);
/* 搜索 */ /* 搜索 */
@@ -298,6 +390,10 @@ const onTabs = () => {
// 已完成order_status = 1 // 已完成order_status = 1
filterParams.statusFilter = 5; filterParams.statusFilter = 5;
break; break;
case 'cancelled':
// 已取消order_status = 2
filterParams.statusFilter = 8;
break;
case 'refunded': case 'refunded':
// 已退款order_status = 6 // 已退款order_status = 6
filterParams.statusFilter = 6; filterParams.statusFilter = 6;
@@ -351,6 +447,183 @@ const query = () => {
loading.value = true; loading.value = true;
}; };
/* 辅助判断函数 */
// 判断是否为取消状态
const isCancelledStatus = (orderStatus?: number) => {
return [2, 3].includes(orderStatus || 0);
};
// 判断是否为退款相关状态
const isRefundStatus = (orderStatus?: number) => {
return [4, 5, 6, 7].includes(orderStatus || 0);
};
// 判断是否可以删除订单
const canDeleteOrder = (order: ShopOrder) => {
// 已完成、已取消、退款成功的订单可以删除
return [1, 2, 6].includes(order.orderStatus || 0);
};
/* 订单操作方法 */
// 修改订单
const handleEditOrder = (record: ShopOrder) => {
message.info('订单修改功能开发中...');
// TODO: 实现订单修改功能
};
// 取消订单
const handleCancelOrder = (record: ShopOrder) => {
Modal.confirm({
title: '确认取消订单',
content: '确定要取消此订单吗?取消后无法恢复。',
onOk: async () => {
try {
await updateShopOrder({
...record,
orderStatus: 2 // 已取消
});
message.success('订单已取消');
reload();
} catch (error: any) {
message.error(error.message || '取消订单失败');
}
}
});
};
// 发货处理
const handleDelivery = (record: ShopOrder) => {
Modal.confirm({
title: '确认发货',
content: '确定要将此订单标记为已发货吗?',
onOk: async () => {
try {
const now = new Date();
const deliveryTime = toDateString(now, 'yyyy-MM-dd HH:mm:ss');
await updateShopOrder({
...record,
deliveryStatus: 20, // 已发货
deliveryTime: deliveryTime
});
message.success('发货成功');
reload();
} catch (error: any) {
message.error(error.message || '发货失败');
}
}
});
};
// 确认收货
const handleConfirmReceive = (record: ShopOrder) => {
Modal.confirm({
title: '确认收货',
content: '确定要将此订单标记为已收货并完成吗?',
onOk: async () => {
try {
await updateShopOrder({
...record,
deliveryStatus: 30, // 已收货
orderStatus: 1 // 已完成
});
message.success('确认收货成功');
reload();
} catch (error: any) {
message.error(error.message || '确认收货失败');
}
}
});
};
// 同意退款
const handleApproveRefund = (record: ShopOrder) => {
Modal.confirm({
title: '同意退款',
content: '确定要同意此订单的退款申请吗?',
onOk: async () => {
try {
const now = new Date();
const refundTime = toDateString(now, 'yyyy-MM-dd HH:mm:ss');
await updateShopOrder({
...record,
orderStatus: 6, // 退款成功
refundTime: refundTime
});
message.success('退款处理成功');
reload();
} catch (error: any) {
message.error(error.message || '退款处理失败');
}
}
});
};
// 拒绝退款
const handleRejectRefund = (record: ShopOrder) => {
Modal.confirm({
title: '拒绝退款',
content: '确定要拒绝此订单的退款申请吗?',
onOk: async () => {
try {
await updateShopOrder({
...record,
orderStatus: 5 // 退款被拒绝
});
message.success('已拒绝退款申请');
reload();
} catch (error: any) {
message.error(error.message || '操作失败');
}
}
});
};
// 重新处理退款
const handleRetryRefund = (record: ShopOrder) => {
Modal.confirm({
title: '重新处理退款',
content: '确定要重新处理此订单的退款吗?',
onOk: async () => {
try {
await updateShopOrder({
...record,
orderStatus: 4 // 退款申请中
});
message.success('已重新提交退款申请');
reload();
} catch (error: any) {
message.error(error.message || '操作失败');
}
}
});
};
// 申请退款
const handleApplyRefund = (record: ShopOrder) => {
Modal.confirm({
title: '申请退款',
content: '确定要为此订单申请退款吗?',
onOk: async () => {
try {
const now = new Date();
const refundApplyTime = toDateString(now, 'yyyy-MM-dd HH:mm:ss');
await updateShopOrder({
...record,
orderStatus: 4, // 退款申请中
refundApplyTime: refundApplyTime
});
message.success('退款申请已提交');
reload();
} catch (error: any) {
message.error(error.message || '申请退款失败');
}
}
});
};
/* 删除单个订单 */ /* 删除单个订单 */
const remove = (row: ShopOrder) => { const remove = (row: ShopOrder) => {
removeShopOrder(row.orderId) removeShopOrder(row.orderId)

View File

@@ -212,6 +212,11 @@ function OrderList(props: OrderListProps) {
reload(); reload();
}; };
// 格式化日期为后端期望的格式
const formatDateForBackend = (date: Date) => {
return dayjs(date).format('YYYY-MM-DD HH:mm:ss');
};
// 确认收货 // 确认收货
const confirmReceive = async (order: ShopOrder) => { const confirmReceive = async (order: ShopOrder) => {
try { try {