consumer模块完成度95%,能编译在安卓端运行,在解决数据获取和页面布局问题

This commit is contained in:
cyh666666
2026-02-27 08:20:43 +08:00
parent e606c597ca
commit b9acce6c35
1554 changed files with 23471 additions and 8551 deletions

View File

@@ -22,7 +22,7 @@
</view>
<!-- 售后列表 -->
<scroll-view class="refund-content" scroll-y @scrolltolower="loadMore">
<scroll-view class="refund-content" direction="vertical" @scrolltolower="loadMore">
<!-- 空状态 -->
<view v-if="refunds.length === 0 && !isLoading" class="empty-refunds">
<text class="empty-icon">🔄</text>
@@ -58,7 +58,7 @@
</view>
<!-- 进度时间线 -->
<view v-if="refund.status_history?.length > 0" class="timeline">
<view v-if="refund.status_history != null && refund.status_history.length > 0" class="timeline">
<view v-for="(step, index) in getTimelineSteps(refund)"
:key="index"
class="timeline-step">
@@ -116,7 +116,7 @@ type RefundProductInfo = {
type RefundOrderItem = {
id: string
product_name: string
sku_specifications: any
sku_specifications: any | null
price: number
quantity: number
product?: RefundProductInfo
@@ -157,27 +157,17 @@ const currentPage = ref<number>(1)
const pageSize = ref<number>(15)
const hasMore = ref<boolean>(true)
// 监听标签页变化
watch(activeTab, () => {
resetData()
loadRefunds()
})
const getCurrentUserId = (): string => {
return supabaseService.getCurrentUserId() ?? ''
}
// 生命周期
onMounted(() => {
loadRefunds()
loadTabCounts()
})
// 重置数据
const resetData = () => {
refunds.value = []
currentPage.value = 1
hasMore.value = true
}
// 加载售后数据
const loadRefunds = async (loadMore: boolean = false) => {
const loadRefunds = async (loadMore: boolean): Promise<void> => {
if (isLoading.value || (!hasMore.value && loadMore)) {
return
}
@@ -197,46 +187,66 @@ const loadRefunds = async (loadMore: boolean = false) => {
let statusList: number[] = []
if (activeTab.value === 'processing') {
statusList = [1, 2] // 待处理和处理中
statusList = [1, 2]
} else if (activeTab.value === 'completed') {
statusList = [3, 4, 5] // 已完成、已取消、已拒绝
statusList = [3, 4, 5]
}
const rawData = await supabaseService.getRefunds(statusList, page, pageSize.value)
// Map data to UI structure (RefundType)
const newRefunds = rawData.map((item: any): RefundType => {
const orderObj: any = item['order'] ?? {}
const dbItems: any[] = (orderObj['ml_order_items'] as any[]) ?? []
const uiItems = dbItems.map((di: any) : RefundOrderItem => ({
id: di['id'] ?? '',
product_name: di['product_name'] ?? '',
sku_specifications: di['specifications'],
price: 0,
quantity: di['quantity'] ?? 1,
product: { images: [di['image_url'] ?? '/static/default-product.png'] }
}))
const newRefunds: Array<RefundType> = []
for (let i: number = 0; i < rawData.length; i++) {
const item = rawData[i] as UTSJSONObject
const orderObjRaw = item.get('order')
const orderObj = (orderObjRaw != null) ? (orderObjRaw as UTSJSONObject) : (new UTSJSONObject())
const dbItemsRaw = orderObj.get('ml_order_items')
const dbItems = (dbItemsRaw != null) ? (dbItemsRaw as any[]) : []
return {
id: item['id'],
user_id: item['user_id'],
order_id: item['order_id'],
refund_no: item['refund_no'],
refund_type: item['refund_type'],
refund_reason: item['refund_reason'],
refund_amount: Number(item['refund_amount']),
status: item['status'],
// Handle missing timeline by defaulting or leaving empty
status_history: (item['status_history'] as RefundStatusHistoryItem[]) ?? [],
created_at: item.created_at,
const uiItems: Array<RefundOrderItem> = []
for (let j: number = 0; j < dbItems.length; j++) {
const di = dbItems[j] as UTSJSONObject
const imgRaw = di.get('image_url')
const imgUrl = (imgRaw != null) ? (imgRaw as string) : '/static/default-product.png'
const productInfo: RefundProductInfo = {
images: [imgUrl]
} as RefundProductInfo
const specRaw = di.get('specifications')
const specifications = (specRaw != null) ? (specRaw as any) : null
const orderItem: RefundOrderItem = {
id: di.getString('id') ?? '',
product_name: di.getString('product_name') ?? '',
sku_specifications: specifications,
price: 0,
quantity: di.getNumber('quantity') ?? 1,
product: productInfo
} as RefundOrderItem
uiItems.push(orderItem)
}
const statusHistoryRaw = item.get('status_history')
const statusHistory = (statusHistoryRaw != null) ? (statusHistoryRaw as RefundStatusHistoryItem[]) : []
const refundItem: RefundType = {
id: item.getString('id') ?? '',
user_id: item.getString('user_id') ?? '',
order_id: item.getString('order_id') ?? '',
refund_no: item.getString('refund_no') ?? '',
refund_type: item.getNumber('refund_type') ?? 1,
refund_reason: item.getString('refund_reason') ?? '',
refund_amount: item.getNumber('refund_amount') ?? 0,
status: item.getNumber('status') ?? 1,
status_history: statusHistory,
created_at: item.getString('created_at') ?? '',
order: {
id: item.order_id,
order_no: orderObj.order_no,
created_at: orderObj.created_at,
id: item.getString('order_id') ?? '',
order_no: orderObj.getString('order_no') ?? '',
created_at: orderObj.getString('created_at') ?? '',
order_items: uiItems
}
} as RefundOrderInfo
} as RefundType
})
newRefunds.push(refundItem)
}
if (loadMore) {
refunds.value.push(...newRefunds)
@@ -254,57 +264,44 @@ const loadRefunds = async (loadMore: boolean = false) => {
}
}
// 加载标签页计数
const loadTabCounts = async () => {
const userId = getCurrentUserId()
if (userId == '') return
try {
const { count, error } = await supa
.from('refunds')
.select('*', { count: 'exact' })
.eq('user_id', userId)
.in('status', [1, 2])
if (error !== null) {
console.error('加载计数失败:', error)
return
}
tabCounts.value.processing = count ?? 0
const processingRefunds = await supabaseService.getRefunds([1, 2], 1, 100)
tabCounts.value.processing = processingRefunds.length
} catch (err) {
console.error('加载计数异常:', err)
}
}
// 获取当前用户ID
const getCurrentUserId = (): string => {
const userStore = uni.getStorageSync('userInfo')
return userStore['id'] ?? ''
}
watch(activeTab, () => {
resetData()
loadRefunds(false)
})
onMounted(() => {
loadRefunds(false)
loadTabCounts()
})
// 获取状态文本
const getStatusText = (status: number): string => {
const statusMap: Record<number, string> = {
1: '处理',
2: '处理中',
3: '已完成',
4: '已取消',
5: '已拒绝'
}
return statusMap[status] ?? '未知状态'
if (status === 1) return '待处理'
if (status === 2) return '处理'
if (status === 3) return '已完成'
if (status === 4) return '已取消'
if (status === 5) return '已拒绝'
return '未知状态'
}
// 获取状态样式类
const getStatusClass = (status: number): string => {
const classMap: Record<number, string> = {
1: 'status-pending',
2: 'status-processing',
3: 'status-completed',
4: 'status-cancelled',
5: 'status-rejected'
}
return classMap[status] ?? 'status-unknown'
if (status === 1) return 'status-pending'
if (status === 2) return 'status-processing'
if (status === 3) return 'status-completed'
if (status === 4) return 'status-cancelled'
if (status === 5) return 'status-rejected'
return 'status-unknown'
}
// 获取商品图片
@@ -337,45 +334,58 @@ const formatTime = (timeStr?: string): string => {
return `${month}-${day}`
}
// 获取时间线步骤
const getTimelineSteps = (refund: RefundType): Array<any> => {
const steps = [
{ status: 0, title: '提交申请', time: refund.created_at },
{ status: 1, title: '商家处理', time: '' },
{ status: 3, title: '退款完成', time: '' }
]
// 如果有状态历史,更新时间和描述
if (refund.status_history) {
refund.status_history.forEach(history => {
if (history.status === 1 || history.status === 2) {
steps[1].time = history.created_at
steps[1].desc = history.remark
} else if (history.status === 3) {
steps[2].time = history.created_at
steps[2].desc = history.remark
}
})
}
// 标记当前状态
return steps.map((step, index) => ({
...step,
active: index === getCurrentStepIndex(refund.status),
completed: index < getCurrentStepIndex(refund.status)
}))
const getCurrentStepIndex = (status: number): number => {
if (status === 1) return 0
if (status === 2) return 1
if (status === 3) return 2
if (status === 4) return 0
if (status === 5) return 1
return 0
}
// 获取当前步骤索引
const getCurrentStepIndex = (status: number): number => {
switch (status) {
case 1: return 0 // 待处理
case 2: return 1 // 处理中
case 3: return 2 // 已完成
case 4: return 0 // 已取消
case 5: return 1 // 已拒绝
default: return 0
type TimelineStepType = {
status: number,
title: string,
time: string,
active: boolean,
completed: boolean,
desc: string
}
const getTimelineSteps = (refund: RefundType): Array<TimelineStepType> => {
const steps: Array<TimelineStepType> = [
{ status: 0, title: '提交申请', time: refund.created_at, active: false, completed: false, desc: '' },
{ status: 1, title: '商家处理', time: '', active: false, completed: false, desc: '' },
{ status: 3, title: '退款完成', time: '', active: false, completed: false, desc: '' }
]
if (refund.status_history != null) {
for (let i: number = 0; i < refund.status_history.length; i++) {
const history = refund.status_history[i]
if (history.status === 1 || history.status === 2) {
steps[1].time = history.created_at ?? ''
steps[1].desc = history.remark ?? ''
} else if (history.status === 3) {
steps[2].time = history.created_at ?? ''
steps[2].desc = history.remark ?? ''
}
}
}
const currentStepIndex = getCurrentStepIndex(refund.status)
const result: Array<TimelineStepType> = []
for (let i: number = 0; i < steps.length; i++) {
const step = steps[i]
result.push({
status: step.status,
title: step.title,
time: step.time,
desc: step.desc,
active: i === currentStepIndex,
completed: i < currentStepIndex
})
}
return result
}
// 切换标签页
@@ -397,45 +407,42 @@ const viewOrder = (orderId: string) => {
})
}
// 取消退款申请
const doCancelRefund = async (refund: RefundType) => {
try {
const result = await supabaseService.createRefund({
id: refund.id,
status: 4
} as any)
if (result.success) {
refund.status = 4
loadTabCounts()
uni.showToast({
title: '已取消',
icon: 'success'
})
} else {
uni.showToast({
title: '取消失败',
icon: 'none'
})
}
} catch (err) {
console.error('取消退款失败:', err)
uni.showToast({
title: '取消失败',
icon: 'none'
})
}
}
const cancelRefund = (refund: RefundType) => {
uni.showModal({
title: '取消申请',
content: '确定要取消这个退款申请吗?',
success: async (res) => {
success: (res) => {
if (res.confirm) {
try {
const { error } = await supa
.from('refunds')
.update({
status: 4, // 已取消
status_history: [...(refund.status_history ?? []), {
status: 4,
remark: '用户取消申请',
created_at: new Date().toISOString()
}]
})
.eq('id', refund.id)
if (error !== null) {
throw error
}
refund.status = 4
loadTabCounts() // 重新加载计数
uni.showToast({
title: '已取消',
icon: 'success'
})
} catch (err) {
console.error('取消退款失败:', err)
uni.showToast({
title: '取消失败',
icon: 'none'
})
}
doCancelRefund(refund)
}
}
})
@@ -455,41 +462,45 @@ const reviewRefund = (refund: RefundType) => {
})
}
// 删除记录
const doDeleteRefund = async (refund: RefundType) => {
try {
const result = await supabaseService.deleteRefund(refund.id)
if (result) {
const newRefunds: Array<RefundType> = []
for (let i: number = 0; i < refunds.value.length; i++) {
if (refunds.value[i].id !== refund.id) {
newRefunds.push(refunds.value[i])
}
}
refunds.value = newRefunds
uni.showToast({
title: '删除成功',
icon: 'success'
})
} else {
uni.showToast({
title: '删除失败',
icon: 'none'
})
}
} catch (err) {
console.error('删除记录失败:', err)
uni.showToast({
title: '删除失败',
icon: 'none'
})
}
}
const deleteRefund = (refund: RefundType) => {
uni.showModal({
title: '删除记录',
content: '确定要删除这个售后记录吗?',
success: async (res) => {
success: (res) => {
if (res.confirm) {
try {
const { error } = await supa
.from('refunds')
.delete()
.eq('id', refund.id)
if (error !== null) {
throw error
}
const index = refunds.value.findIndex(r => r.id === refund.id)
if (index !== -1) {
refunds.value.splice(index, 1)
refunds.value = [...refunds.value]
}
uni.showToast({
title: '删除成功',
icon: 'success'
})
} catch (err) {
console.error('删除记录失败:', err)
uni.showToast({
title: '删除失败',
icon: 'none'
})
}
doDeleteRefund(refund)
}
}
})