feat: 初次提交我的项目代码
This commit is contained in:
858
pages/mall/consumer/refund.uvue
Normal file
858
pages/mall/consumer/refund.uvue
Normal file
@@ -0,0 +1,858 @@
|
||||
<!-- 退款页面 -->
|
||||
<template>
|
||||
<view class="refund-page">
|
||||
<!-- 顶部栏 -->
|
||||
<view class="refund-header">
|
||||
<text class="back-btn" @click="goBack">‹</text>
|
||||
<text class="header-title">退款/售后</text>
|
||||
</view>
|
||||
|
||||
<!-- 标签页 -->
|
||||
<view class="refund-tabs">
|
||||
<view :class="['refund-tab', { active: activeTab === 'all' }]" @click="changeTab('all')">
|
||||
<text class="tab-text">全部</text>
|
||||
</view>
|
||||
<view :class="['refund-tab', { active: activeTab === 'processing' }]" @click="changeTab('processing')">
|
||||
<text class="tab-text">处理中</text>
|
||||
<text v-if="tabCounts.processing > 0" class="tab-badge">{{ tabCounts.processing }}</text>
|
||||
</view>
|
||||
<view :class="['refund-tab', { active: activeTab === 'completed' }]" @click="changeTab('completed')">
|
||||
<text class="tab-text">已完成</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 售后列表 -->
|
||||
<scroll-view class="refund-content" scroll-y @scrolltolower="loadMore">
|
||||
<!-- 空状态 -->
|
||||
<view v-if="refunds.length === 0 && !isLoading" class="empty-refunds">
|
||||
<text class="empty-icon">🔄</text>
|
||||
<text class="empty-text">暂无售后记录</text>
|
||||
<text class="empty-subtext">您可以在订单详情中申请售后</text>
|
||||
<button class="go-orders-btn" @click="goToOrders">查看订单</button>
|
||||
</view>
|
||||
|
||||
<!-- 售后项 -->
|
||||
<view v-for="refund in refunds" :key="refund.id" class="refund-item">
|
||||
<view class="refund-header">
|
||||
<text class="refund-no">售后单号: {{ refund.refund_no }}</text>
|
||||
<text :class="['refund-status', getStatusClass(refund.status)]">
|
||||
{{ getStatusText(refund.status) }}
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<view class="order-info">
|
||||
<text class="order-no">订单号: {{ refund.order?.order_no }}</text>
|
||||
<text class="order-time">{{ formatTime(refund.order?.created_at) }}</text>
|
||||
</view>
|
||||
|
||||
<view class="product-info" @click="viewOrder(refund.order_id)">
|
||||
<image class="product-image" :src="getProductImage(refund)" />
|
||||
<view class="product-details">
|
||||
<text class="product-name">{{ getProductName(refund) }}</text>
|
||||
<text v-if="refund.refund_reason" class="refund-reason">原因: {{ refund.refund_reason }}</text>
|
||||
<view class="refund-amount">
|
||||
<text class="amount-label">退款金额:</text>
|
||||
<text class="amount-value">¥{{ refund.refund_amount }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 进度时间线 -->
|
||||
<view v-if="refund.status_history?.length > 0" class="timeline">
|
||||
<view v-for="(step, index) in getTimelineSteps(refund)"
|
||||
:key="index"
|
||||
class="timeline-step">
|
||||
<view class="step-dot" :class="{ active: step.active, completed: step.completed }"></view>
|
||||
<view class="step-info">
|
||||
<text class="step-title">{{ step.title }}</text>
|
||||
<text class="step-time">{{ step.time }}</text>
|
||||
<text v-if="step.desc" class="step-desc">{{ step.desc }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<view v-if="refund.status === 1" class="refund-actions">
|
||||
<button class="action-btn cancel" @click="cancelRefund(refund)">取消申请</button>
|
||||
<button class="action-btn contact" @click="contactService(refund)">联系客服</button>
|
||||
</view>
|
||||
|
||||
<view v-if="refund.status === 3" class="refund-actions">
|
||||
<button class="action-btn review" @click="reviewRefund(refund)">评价服务</button>
|
||||
<button class="action-btn delete" @click="deleteRefund(refund)">删除记录</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多 -->
|
||||
<view v-if="isLoading" class="loading-more">
|
||||
<text class="loading-text">加载中...</text>
|
||||
</view>
|
||||
<view v-if="!hasMore && refunds.length > 0" class="no-more">
|
||||
<text class="no-more-text">没有更多了</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 申请售后按钮 -->
|
||||
<view class="apply-btn-container">
|
||||
<button class="apply-btn" @click="applyRefund">申请售后</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref, onMounted, watch } from 'vue'
|
||||
import supa from '@/components/supadb/aksupainstance.uts'
|
||||
|
||||
type RefundType = {
|
||||
id: string
|
||||
user_id: string
|
||||
order_id: string
|
||||
refund_no: string
|
||||
refund_type: number // 1:仅退款 2:退货退款
|
||||
refund_reason: string
|
||||
refund_amount: number
|
||||
status: number // 1:待处理 2:处理中 3:已完成 4:已取消 5:已拒绝
|
||||
status_history: Array<{
|
||||
status: number
|
||||
remark: string
|
||||
created_at: string
|
||||
}> | null
|
||||
created_at: string
|
||||
order?: {
|
||||
id: string
|
||||
order_no: string
|
||||
created_at: string
|
||||
order_items: Array<{
|
||||
id: string
|
||||
product_name: string
|
||||
sku_specifications: any
|
||||
price: number
|
||||
quantity: number
|
||||
product?: {
|
||||
images: string[]
|
||||
}
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
type TabCountsType = {
|
||||
processing: number
|
||||
}
|
||||
|
||||
const activeTab = ref<string>('all')
|
||||
const refunds = ref<Array<RefundType>>([])
|
||||
const tabCounts = ref<TabCountsType>({
|
||||
processing: 0
|
||||
})
|
||||
const isLoading = ref<boolean>(false)
|
||||
const currentPage = ref<number>(1)
|
||||
const pageSize = ref<number>(15)
|
||||
const hasMore = ref<boolean>(true)
|
||||
|
||||
// 监听标签页变化
|
||||
watch(activeTab, () => {
|
||||
resetData()
|
||||
loadRefunds()
|
||||
})
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
loadRefunds()
|
||||
loadTabCounts()
|
||||
})
|
||||
|
||||
// 重置数据
|
||||
const resetData = () => {
|
||||
refunds.value = []
|
||||
currentPage.value = 1
|
||||
hasMore.value = true
|
||||
}
|
||||
|
||||
// 加载售后数据
|
||||
const loadRefunds = async (loadMore: boolean = false) => {
|
||||
if (isLoading.value || (!hasMore.value && loadMore)) {
|
||||
return
|
||||
}
|
||||
|
||||
isLoading.value = true
|
||||
|
||||
try {
|
||||
const userId = getCurrentUserId()
|
||||
if (!userId) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/user/login'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const page = loadMore ? currentPage.value + 1 : 1
|
||||
|
||||
let query = supa
|
||||
.from('refunds')
|
||||
.select(`
|
||||
*,
|
||||
order:order_id(
|
||||
order_no,
|
||||
created_at,
|
||||
order_items(
|
||||
*,
|
||||
product:product_id(images)
|
||||
)
|
||||
)
|
||||
`)
|
||||
.eq('user_id', userId)
|
||||
.order('created_at', { ascending: false })
|
||||
|
||||
// 根据标签页过滤
|
||||
if (activeTab.value === 'processing') {
|
||||
query = query.in('status', [1, 2]) // 待处理和处理中
|
||||
} else if (activeTab.value === 'completed') {
|
||||
query = query.in('status', [3, 4, 5]) // 已完成、已取消、已拒绝
|
||||
}
|
||||
|
||||
// 分页
|
||||
query = query.range((page - 1) * pageSize.value, page * pageSize.value - 1)
|
||||
|
||||
const { data, error } = await query
|
||||
|
||||
if (error !== null) {
|
||||
console.error('加载售后记录失败:', error)
|
||||
return
|
||||
}
|
||||
|
||||
const newRefunds = data || []
|
||||
|
||||
if (loadMore) {
|
||||
refunds.value.push(...newRefunds)
|
||||
currentPage.value = page
|
||||
} else {
|
||||
refunds.value = newRefunds
|
||||
currentPage.value = 1
|
||||
}
|
||||
|
||||
hasMore.value = newRefunds.length === pageSize.value
|
||||
} catch (err) {
|
||||
console.error('加载售后记录异常:', err)
|
||||
} finally {
|
||||
isLoading.value = 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
|
||||
} catch (err) {
|
||||
console.error('加载计数异常:', err)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取当前用户ID
|
||||
const getCurrentUserId = (): string => {
|
||||
const userStore = uni.getStorageSync('userInfo')
|
||||
return userStore?.id || ''
|
||||
}
|
||||
|
||||
// 获取状态文本
|
||||
const getStatusText = (status: number): string => {
|
||||
const statusMap: Record<number, string> = {
|
||||
1: '待处理',
|
||||
2: '处理中',
|
||||
3: '已完成',
|
||||
4: '已取消',
|
||||
5: '已拒绝'
|
||||
}
|
||||
return statusMap[status] || '未知状态'
|
||||
}
|
||||
|
||||
// 获取状态样式类
|
||||
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'
|
||||
}
|
||||
|
||||
// 获取商品图片
|
||||
const getProductImage = (refund: RefundType): string => {
|
||||
const firstItem = refund.order?.order_items?.[0]
|
||||
if (!firstItem?.product?.images?.[0]) {
|
||||
return '/static/default-product.png'
|
||||
}
|
||||
return firstItem.product.images[0]
|
||||
}
|
||||
|
||||
// 获取商品名称
|
||||
const getProductName = (refund: RefundType): string => {
|
||||
const items = refund.order?.order_items || []
|
||||
if (items.length === 0) return '未知商品'
|
||||
|
||||
if (items.length === 1) {
|
||||
return items[0].product_name
|
||||
} else {
|
||||
return `${items[0].product_name}等${items.length}件商品`
|
||||
}
|
||||
}
|
||||
|
||||
// 格式化时间
|
||||
const formatTime = (timeStr?: string): string => {
|
||||
if (!timeStr) return ''
|
||||
const date = new Date(timeStr)
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, '0')
|
||||
const day = date.getDate().toString().padStart(2, '0')
|
||||
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 => {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// 切换标签页
|
||||
const changeTab = (tab: string) => {
|
||||
activeTab.value = tab
|
||||
}
|
||||
|
||||
// 加载更多
|
||||
const loadMore = () => {
|
||||
if (hasMore.value && !isLoading.value) {
|
||||
loadRefunds(true)
|
||||
}
|
||||
}
|
||||
|
||||
// 查看订单
|
||||
const viewOrder = (orderId: string) => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/mall/consumer/order-detail?id=${orderId}`
|
||||
})
|
||||
}
|
||||
|
||||
// 取消退款申请
|
||||
const cancelRefund = (refund: RefundType) => {
|
||||
uni.showModal({
|
||||
title: '取消申请',
|
||||
content: '确定要取消这个退款申请吗?',
|
||||
success: async (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'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 联系客服
|
||||
const contactService = (refund: RefundType) => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/mall/service/chat?refundId=${refund.id}`
|
||||
})
|
||||
}
|
||||
|
||||
// 评价服务
|
||||
const reviewRefund = (refund: RefundType) => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/mall/consumer/refund-review?id=${refund.id}`
|
||||
})
|
||||
}
|
||||
|
||||
// 删除记录
|
||||
const deleteRefund = (refund: RefundType) => {
|
||||
uni.showModal({
|
||||
title: '删除记录',
|
||||
content: '确定要删除这个售后记录吗?',
|
||||
success: async (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'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 申请售后
|
||||
const applyRefund = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/mall/consumer/apply-refund'
|
||||
})
|
||||
}
|
||||
|
||||
// 查看订单
|
||||
const goToOrders = () => {
|
||||
uni.switchTab({
|
||||
url: '/pages/mall/consumer/orders'
|
||||
})
|
||||
}
|
||||
|
||||
// 返回
|
||||
const goBack = () => {
|
||||
uni.navigateBack()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.refund-page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.refund-header {
|
||||
background-color: #ffffff;
|
||||
padding: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
font-size: 24px;
|
||||
color: #333333;
|
||||
padding: 5px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.refund-tabs {
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.refund-tab {
|
||||
flex: 1;
|
||||
padding: 15px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.refund-tab.active {
|
||||
color: #007aff;
|
||||
}
|
||||
|
||||
.refund-tab.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background-color: #007aff;
|
||||
}
|
||||
|
||||
.tab-text {
|
||||
font-size: 16px;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.refund-tab.active .tab-text {
|
||||
color: #007aff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tab-badge {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 20px;
|
||||
background-color: #ff4757;
|
||||
color: #ffffff;
|
||||
font-size: 10px;
|
||||
padding: 2px 5px;
|
||||
border-radius: 8px;
|
||||
min-width: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.refund-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.empty-refunds {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 80px 20px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 80px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 16px;
|
||||
color: #666666;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.empty-subtext {
|
||||
font-size: 14px;
|
||||
color: #999999;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.go-orders-btn {
|
||||
background-color: #007aff;
|
||||
color: #ffffff;
|
||||
padding: 10px 40px;
|
||||
border-radius: 25px;
|
||||
font-size: 14px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.refund-item {
|
||||
background-color: #ffffff;
|
||||
margin-bottom: 10px;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.refund-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
}
|
||||
|
||||
.refund-no {
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.refund-status {
|
||||
font-size: 14px;
|
||||
padding: 4px 10px;
|
||||
border-radius: 12px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.status-pending {
|
||||
background-color: #ffa726;
|
||||
}
|
||||
|
||||
.status-processing {
|
||||
background-color: #2196f3;
|
||||
}
|
||||
|
||||
.status-completed {
|
||||
background-color: #4caf50;
|
||||
}
|
||||
|
||||
.status-cancelled {
|
||||
background-color: #9e9e9e;
|
||||
}
|
||||
|
||||
.status-rejected {
|
||||
background-color: #f44336;
|
||||
}
|
||||
|
||||
.order-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
}
|
||||
|
||||
.order-no {
|
||||
font-size: 13px;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.order-time {
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.product-info {
|
||||
display: flex;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.product-image {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 5px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.product-details {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.product-name {
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
line-height: 1.4;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.refund-reason {
|
||||
font-size: 12px;
|
||||
color: #666666;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.refund-amount {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.amount-label {
|
||||
font-size: 13px;
|
||||
color: #666666;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.amount-value {
|
||||
font-size: 16px;
|
||||
color: #ff4757;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.timeline {
|
||||
padding: 15px 0;
|
||||
border-top: 1px solid #f5f5f5;
|
||||
}
|
||||
|
||||
.timeline-step {
|
||||
display: flex;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.timeline-step:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.step-dot {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 6px;
|
||||
border: 2px solid #e5e5e5;
|
||||
margin-right: 15px;
|
||||
position: relative;
|
||||
top: 3px;
|
||||
}
|
||||
|
||||
.step-dot.active {
|
||||
border-color: #007aff;
|
||||
background-color: #007aff;
|
||||
}
|
||||
|
||||
.step-dot.completed {
|
||||
border-color: #4caf50;
|
||||
background-color: #4caf50;
|
||||
}
|
||||
|
||||
.step-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.step-title {
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
font-weight: bold;
|
||||
margin-bottom: 3px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.step-time {
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
margin-bottom: 3px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.step-desc {
|
||||
font-size: 12px;
|
||||
color: #666666;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.refund-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
padding-top: 15px;
|
||||
border-top: 1px solid #f5f5f5;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 8px 15px;
|
||||
border-radius: 15px;
|
||||
font-size: 12px;
|
||||
border: 1px solid;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.action-btn.cancel {
|
||||
border-color: #666666;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.action-btn.contact {
|
||||
border-color: #007aff;
|
||||
color: #007aff;
|
||||
}
|
||||
|
||||
.action-btn.review {
|
||||
border-color: #ffa726;
|
||||
color: #ffa726;
|
||||
}
|
||||
|
||||
.action-btn.delete {
|
||||
border-color: #f44336;
|
||||
color: #f44336;
|
||||
}
|
||||
|
||||
.loading-more,
|
||||
.no-more {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.loading-text,
|
||||
.no-more-text {
|
||||
color: #999999;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.apply-btn-container {
|
||||
background-color: #ffffff;
|
||||
padding: 15px;
|
||||
border-top: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.apply-btn {
|
||||
background-color: #007aff;
|
||||
color: #ffffff;
|
||||
height: 50px;
|
||||
border-radius: 25px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user