```
feat(registration): 优化经销商注册流程并增加地址定位功能 - 修改导航栏标题从“邀请注册”为“注册成为会员” - 修复重复提交问题并移除不必要的submitting状态 - 增加昵称和头像的必填验证提示 - 添加用户角色缺失时的默认角色写入机制 - 集成地图选点功能,支持经纬度获取和地址解析 - 实现微信地址导入功能,自动填充基本信息 - 增加定位权限检查和错误处理机制 - 添加.gitignore规则忽略备份文件夹src__bak - 移除已废弃的银行卡和客户管理页面代码 - 优化表单验证规则和错误提示信息 - 实现经销商注册成功后自动跳转到“我的”页面 - 添加用户信息缓存刷新机制确保角色信息同步 ```
This commit is contained in:
320
src/api/afterSale.ts
Normal file
320
src/api/afterSale.ts
Normal file
@@ -0,0 +1,320 @@
|
||||
import { request } from '../utils/request'
|
||||
|
||||
// 售后类型
|
||||
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
|
||||
images?: string[]
|
||||
}
|
||||
|
||||
// 售后详情
|
||||
export interface AfterSaleDetail {
|
||||
id: string
|
||||
orderId: string
|
||||
orderNo: 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
|
||||
startTime?: string
|
||||
endTime?: string
|
||||
}
|
||||
|
||||
// 售后列表响应
|
||||
export interface AfterSaleListResponse {
|
||||
success: boolean
|
||||
data: {
|
||||
list: AfterSaleDetail[]
|
||||
total: number
|
||||
page: number
|
||||
pageSize: number
|
||||
}
|
||||
message?: string
|
||||
}
|
||||
|
||||
// 售后详情响应
|
||||
export interface AfterSaleDetailResponse {
|
||||
success: boolean
|
||||
data: AfterSaleDetail
|
||||
message?: string
|
||||
}
|
||||
|
||||
// 售后类型映射
|
||||
export const AFTER_SALE_TYPE_MAP = {
|
||||
'refund': '退款',
|
||||
'return': '退货',
|
||||
'exchange': '换货',
|
||||
'repair': '维修'
|
||||
}
|
||||
|
||||
// 售后状态映射
|
||||
export const AFTER_SALE_STATUS_MAP = {
|
||||
'pending': '待审核',
|
||||
'approved': '已同意',
|
||||
'rejected': '已拒绝',
|
||||
'processing': '处理中',
|
||||
'completed': '已完成',
|
||||
'cancelled': '已取消'
|
||||
}
|
||||
|
||||
// 状态颜色映射
|
||||
export const STATUS_COLOR_MAP = {
|
||||
'pending': '#faad14',
|
||||
'approved': '#52c41a',
|
||||
'rejected': '#ff4d4f',
|
||||
'processing': '#1890ff',
|
||||
'completed': '#52c41a',
|
||||
'cancelled': '#999'
|
||||
}
|
||||
|
||||
// 申请售后
|
||||
export const applyAfterSale = async (params: AfterSaleApplyParams): Promise<AfterSaleDetailResponse> => {
|
||||
try {
|
||||
const response = await request<AfterSaleDetailResponse>({
|
||||
url: '/api/after-sale/apply',
|
||||
method: 'POST',
|
||||
data: params
|
||||
})
|
||||
|
||||
return response
|
||||
} catch (error) {
|
||||
console.error('申请售后失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 查询售后详情
|
||||
export const getAfterSaleDetail = async (params: {
|
||||
orderId?: string
|
||||
afterSaleId?: string
|
||||
}): Promise<AfterSaleDetailResponse> => {
|
||||
try {
|
||||
const response = await request<AfterSaleDetailResponse>({
|
||||
url: '/api/after-sale/detail',
|
||||
method: 'GET',
|
||||
data: params
|
||||
})
|
||||
|
||||
return response
|
||||
} catch (error) {
|
||||
console.error('查询售后详情失败:', error)
|
||||
|
||||
// 返回模拟数据作为降级方案
|
||||
return getMockAfterSaleDetail(params)
|
||||
}
|
||||
}
|
||||
|
||||
// 查询售后列表
|
||||
export const getAfterSaleList = async (params: AfterSaleListParams): Promise<AfterSaleListResponse> => {
|
||||
try {
|
||||
const response = await request<AfterSaleListResponse>({
|
||||
url: '/api/after-sale/list',
|
||||
method: 'GET',
|
||||
data: params
|
||||
})
|
||||
|
||||
return response
|
||||
} catch (error) {
|
||||
console.error('查询售后列表失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 撤销售后申请
|
||||
export const cancelAfterSale = async (afterSaleId: string): Promise<{ success: boolean; message?: string }> => {
|
||||
try {
|
||||
const response = await request<{ success: boolean; message?: string }>({
|
||||
url: '/api/after-sale/cancel',
|
||||
method: 'POST',
|
||||
data: { afterSaleId }
|
||||
})
|
||||
|
||||
return response
|
||||
} catch (error) {
|
||||
console.error('撤销售后申请失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 获取模拟售后详情数据
|
||||
const getMockAfterSaleDetail = (params: {
|
||||
orderId?: string
|
||||
afterSaleId?: string
|
||||
}): AfterSaleDetailResponse => {
|
||||
const now = new Date()
|
||||
const yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000)
|
||||
const twoDaysAgo = new Date(now.getTime() - 2 * 24 * 60 * 60 * 1000)
|
||||
|
||||
const mockData: AfterSaleDetailResponse = {
|
||||
success: true,
|
||||
data: {
|
||||
id: 'AS' + Date.now(),
|
||||
orderId: params.orderId || '',
|
||||
orderNo: 'ORD' + Date.now(),
|
||||
type: 'refund',
|
||||
status: 'processing',
|
||||
reason: '商品质量问题',
|
||||
description: '收到的商品有明显瑕疵,包装破损,希望申请退款处理',
|
||||
amount: 9999,
|
||||
applyTime: twoDaysAgo.toISOString(),
|
||||
processTime: yesterday.toISOString(),
|
||||
contactPhone: '138****5678',
|
||||
evidenceImages: [
|
||||
'https://via.placeholder.com/200x200?text=Evidence1',
|
||||
'https://via.placeholder.com/200x200?text=Evidence2'
|
||||
],
|
||||
progressRecords: [
|
||||
{
|
||||
id: '1',
|
||||
time: now.toISOString(),
|
||||
status: '处理中',
|
||||
description: '客服正在处理您的申请,请耐心等待',
|
||||
operator: '客服小王',
|
||||
remark: '预计1-2个工作日内完成处理'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
time: new Date(now.getTime() - 4 * 60 * 60 * 1000).toISOString(),
|
||||
status: '已审核',
|
||||
description: '您的申请已通过审核,正在安排退款处理',
|
||||
operator: '审核员张三'
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
time: yesterday.toISOString(),
|
||||
status: '已受理',
|
||||
description: '我们已收到您的申请,正在进行审核',
|
||||
operator: '系统'
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
time: twoDaysAgo.toISOString(),
|
||||
status: '已提交',
|
||||
description: '您已成功提交售后申请',
|
||||
operator: '用户'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
return mockData
|
||||
}
|
||||
|
||||
// 格式化售后状态
|
||||
export const formatAfterSaleStatus = (status: AfterSaleStatus): {
|
||||
text: string
|
||||
color: string
|
||||
icon: string
|
||||
} => {
|
||||
const statusMap = {
|
||||
'pending': { text: '待审核', color: '#faad14', icon: '⏳' },
|
||||
'approved': { text: '已同意', color: '#52c41a', icon: '✅' },
|
||||
'rejected': { text: '已拒绝', color: '#ff4d4f', icon: '❌' },
|
||||
'processing': { text: '处理中', color: '#1890ff', icon: '🔄' },
|
||||
'completed': { text: '已完成', color: '#52c41a', icon: '✅' },
|
||||
'cancelled': { text: '已取消', color: '#999', icon: '⭕' }
|
||||
}
|
||||
|
||||
return statusMap[status] || { text: status, color: '#666', icon: '📋' }
|
||||
}
|
||||
|
||||
// 计算预计处理时间
|
||||
export const calculateEstimatedTime = (
|
||||
applyTime: string,
|
||||
type: AfterSaleType,
|
||||
status: AfterSaleStatus
|
||||
): string => {
|
||||
const applyDate = new Date(applyTime)
|
||||
let estimatedDays = 3 // 默认3个工作日
|
||||
|
||||
// 根据售后类型调整预计时间
|
||||
switch (type) {
|
||||
case 'refund':
|
||||
estimatedDays = 3 // 退款3个工作日
|
||||
break
|
||||
case 'return':
|
||||
estimatedDays = 7 // 退货7个工作日
|
||||
break
|
||||
case 'exchange':
|
||||
estimatedDays = 10 // 换货10个工作日
|
||||
break
|
||||
case 'repair':
|
||||
estimatedDays = 15 // 维修15个工作日
|
||||
break
|
||||
}
|
||||
|
||||
// 根据当前状态调整
|
||||
if (status === 'completed') {
|
||||
return '已完成'
|
||||
} else if (status === 'rejected' || status === 'cancelled') {
|
||||
return '已结束'
|
||||
}
|
||||
|
||||
const estimatedDate = new Date(applyDate.getTime() + estimatedDays * 24 * 60 * 60 * 1000)
|
||||
return `预计${estimatedDate.getMonth() + 1}月${estimatedDate.getDate()}日前完成`
|
||||
}
|
||||
|
||||
// 获取售后进度步骤
|
||||
export const getAfterSaleSteps = (type: AfterSaleType, status: AfterSaleStatus) => {
|
||||
const baseSteps = [
|
||||
{ title: '提交申请', description: '用户提交售后申请' },
|
||||
{ title: '审核中', description: '客服审核申请材料' },
|
||||
{ title: '处理中', description: '正在处理您的申请' },
|
||||
{ title: '完成', description: '售后处理完成' }
|
||||
]
|
||||
|
||||
// 根据类型调整步骤
|
||||
if (type === 'return' || type === 'exchange') {
|
||||
baseSteps.splice(2, 0, { title: '等待收货', description: '等待用户寄回商品' })
|
||||
baseSteps.splice(3, 0, { title: '确认收货', description: '商家确认收到退回商品' })
|
||||
}
|
||||
|
||||
return baseSteps
|
||||
}
|
||||
Reference in New Issue
Block a user