- 新增地址类型定义,增强前端地址数据结构 - 新增地址编辑页面,支持地址智能识别和定位选点功能 - 地址编辑支持省市区选择及默认地址设置 - 新增地址列表页面,支持地址展示、删除、编辑和选择功能 - 实现售后申请页面,支持选择售后类型和退款原因 - 售后申请支持商品选择、退款金额计算和凭证上传 - 新增售后详情页面,支持售后状态展示及申请取消 - 优化页面加载和用户交互体验,增加错误提示和权限处理
155 lines
3.8 KiB
TypeScript
155 lines
3.8 KiB
TypeScript
import request from '@/utils/request'
|
|
import type { ApiResult, PageResult } from '@/api'
|
|
|
|
// 售后类型
|
|
export type AfterSaleType = 'refund' | 'return' | 'exchange' | 'repair'
|
|
|
|
// 售后状态
|
|
export type AfterSaleStatus =
|
|
| 'pending' // 待审核
|
|
| 'approved' // 已同意
|
|
| 'rejected' // 已拒绝
|
|
| 'processing' // 处理中
|
|
| 'completed' // 已完成
|
|
| 'cancelled' // 已取消
|
|
|
|
// 售后进度记录
|
|
export interface ProgressRecord {
|
|
id: string
|
|
time: string
|
|
status: string
|
|
description: string
|
|
operator?: string
|
|
remark?: string
|
|
}
|
|
|
|
// 售后详情
|
|
export interface AfterSaleDetail {
|
|
id: string
|
|
orderId: string
|
|
orderNo: string
|
|
goodsName?: string
|
|
type: AfterSaleType
|
|
status: AfterSaleStatus
|
|
reason: string
|
|
description: string
|
|
amount: number
|
|
applyTime: string
|
|
processTime?: string
|
|
completeTime?: string
|
|
rejectReason?: string
|
|
contactPhone?: string
|
|
evidenceImages: string[]
|
|
progressRecords: ProgressRecord[]
|
|
}
|
|
|
|
// 售后申请参数
|
|
export interface AfterSaleApplyParams {
|
|
orderId: string
|
|
type: AfterSaleType
|
|
reason: string
|
|
description?: string
|
|
amount?: number
|
|
contactPhone?: string
|
|
evidenceImages?: string[]
|
|
goodsItems?: Array<{ goodsId: string; quantity: number }>
|
|
}
|
|
|
|
// 售后列表查询参数
|
|
export interface AfterSaleListParams {
|
|
page?: number
|
|
pageSize?: number
|
|
status?: AfterSaleStatus
|
|
type?: AfterSaleType
|
|
}
|
|
|
|
// 售后类型映射
|
|
export const AFTER_SALE_TYPE_MAP: Record<AfterSaleType, string> = {
|
|
refund: '退款',
|
|
return: '退货',
|
|
exchange: '换货',
|
|
repair: '维修',
|
|
}
|
|
|
|
// 售后状态映射
|
|
export const AFTER_SALE_STATUS_MAP: Record<AfterSaleStatus, string> = {
|
|
pending: '待审核',
|
|
approved: '已同意',
|
|
rejected: '已拒绝',
|
|
processing: '处理中',
|
|
completed: '已完成',
|
|
cancelled: '已取消',
|
|
}
|
|
|
|
// 格式化售后状态
|
|
export const formatAfterSaleStatus = (status: AfterSaleStatus): {
|
|
text: string
|
|
color: string
|
|
icon: string
|
|
} => {
|
|
const statusMap: Record<AfterSaleStatus, { text: string; color: string; icon: string }> = {
|
|
pending: { text: '待审核', color: 'text-orange-500', icon: '⏳' },
|
|
approved: { text: '已同意', color: 'text-green-500', icon: '✅' },
|
|
rejected: { text: '已拒绝', color: 'text-red-500', icon: '❌' },
|
|
processing: { text: '处理中', color: 'text-blue-500', icon: '🔄' },
|
|
completed: { text: '已完成', color: 'text-green-500', icon: '✅' },
|
|
cancelled: { text: '已取消', color: 'text-gray-400', icon: '⭕' },
|
|
}
|
|
return statusMap[status] || { text: status, color: 'text-gray-400', icon: '📋' }
|
|
}
|
|
|
|
/**
|
|
* 申请售后
|
|
*/
|
|
export async function applyAfterSale(data: AfterSaleApplyParams) {
|
|
const res = await request.post<ApiResult<AfterSaleDetail>>(
|
|
'/shop/shop-after-sale/apply',
|
|
data
|
|
)
|
|
if (res.code === 0) {
|
|
return res.data
|
|
}
|
|
return Promise.reject(new Error(res.message))
|
|
}
|
|
|
|
/**
|
|
* 分页查询售后列表
|
|
*/
|
|
export async function pageAfterSaleList(params: AfterSaleListParams) {
|
|
const res = await request.get<ApiResult<PageResult<AfterSaleDetail>>>(
|
|
'/shop/shop-after-sale/page',
|
|
params
|
|
)
|
|
if (res.code === 0) {
|
|
return res.data
|
|
}
|
|
return Promise.reject(new Error(res.message))
|
|
}
|
|
|
|
/**
|
|
* 查询售后详情
|
|
*/
|
|
export async function getAfterSaleDetail(id: string) {
|
|
const res = await request.get<ApiResult<AfterSaleDetail>>(
|
|
'/shop/shop-after-sale/' + id
|
|
)
|
|
if (res.code === 0 && res.data) {
|
|
return res.data
|
|
}
|
|
return Promise.reject(new Error(res.message))
|
|
}
|
|
|
|
/**
|
|
* 撤销售后申请
|
|
*/
|
|
export async function cancelAfterSale(id: string) {
|
|
const res = await request.post<ApiResult<unknown>>(
|
|
'/shop/shop-after-sale/cancel',
|
|
{ id }
|
|
)
|
|
if (res.code === 0) {
|
|
return res.message
|
|
}
|
|
return Promise.reject(new Error(res.message))
|
|
}
|