844 lines
21 KiB
Vue
844 lines
21 KiB
Vue
<template>
|
|
<view class="billing-center-page">
|
|
<!-- 自定义导航栏 -->
|
|
<view class="custom-nav safe-area-top">
|
|
<view class="nav-content">
|
|
<view class="nav-btn" @click="goBack">
|
|
<uni-icons type="left" size="22" color="#1E293B"></uni-icons>
|
|
</view>
|
|
<text class="nav-title">计费中心</text>
|
|
<view class="nav-btn" @click="refreshData">
|
|
<uni-icons type="refresh" size="20" color="#64748B"></uni-icons>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<scroll-view scroll-y class="page-content" @scrolltolower="loadMore">
|
|
<!-- 计费状态卡片 -->
|
|
<view class="status-card" :class="billingStatusClass">
|
|
<view class="status-header">
|
|
<view class="status-icon">
|
|
<uni-icons :type="statusIcon" size="32" color="#FFFFFF"></uni-icons>
|
|
</view>
|
|
<view class="status-info">
|
|
<text class="status-title">{{statusTitle}}</text>
|
|
<text class="status-desc">{{statusDesc}}</text>
|
|
</view>
|
|
</view>
|
|
<view class="status-progress" v-if="daysLeft > 0">
|
|
<view class="progress-bar">
|
|
<view class="progress-fill" :style="{width: progressPercent + '%', background: progressColor}"></view>
|
|
</view>
|
|
<text class="days-left">剩余 {{daysLeft}} 天</text>
|
|
</view>
|
|
<view class="status-action" v-if="needRenewal">
|
|
<button class="renew-btn" @click="goToPlanSelect">立即续费</button>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 当前套餐 -->
|
|
<view class="section-card" v-if="billingInfo.plan">
|
|
<view class="card-header">
|
|
<view class="header-left">
|
|
<uni-icons type="vip-filled" size="20" color="#667eea"></uni-icons>
|
|
<text class="header-title">当前套餐</text>
|
|
</view>
|
|
<view class="plan-tag" :class="planTagType">{{billingInfoStatusText}}</view>
|
|
</view>
|
|
<view class="plan-content">
|
|
<view class="plan-main">
|
|
<text class="plan-name">{{billingInfo.plan.name}}</text>
|
|
<view class="plan-price">
|
|
<text class="price">¥{{billingInfo.plan.monthlyPrice}}</text>
|
|
<text class="unit">/月</text>
|
|
</view>
|
|
</view>
|
|
<text class="plan-desc">{{billingInfo.plan.description}}</text>
|
|
<view class="plan-resources">
|
|
<view class="resource-item">
|
|
<uni-icons type="home-filled" size="16" color="#667eea"></uni-icons>
|
|
<text>{{billingInfo.plan.maxApartments}} 栋公寓</text>
|
|
</view>
|
|
<view class="resource-item">
|
|
<uni-icons type="shop-filled" size="16" color="#667eea"></uni-icons>
|
|
<text>{{billingInfo.plan.maxRooms}} 个房间</text>
|
|
</view>
|
|
<view class="resource-item">
|
|
<uni-icons type="person-filled" size="16" color="#667eea"></uni-icons>
|
|
<text>{{billingInfo.plan.maxUsers}} 个用户</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 资源使用 -->
|
|
<view class="section-card">
|
|
<view class="card-header">
|
|
<view class="header-left">
|
|
<uni-icons type="chart-filled" size="20" color="#667eea"></uni-icons>
|
|
<text class="header-title">资源使用</text>
|
|
</view>
|
|
<text class="refresh-text" @click="refreshUsage">刷新</text>
|
|
</view>
|
|
<view class="usage-list" v-if="usageStats">
|
|
<view class="usage-item">
|
|
<view class="usage-label">
|
|
<uni-icons type="home-filled" size="16" color="#409EFF"></uni-icons>
|
|
<text>公寓</text>
|
|
</view>
|
|
<view class="usage-bar">
|
|
<view class="progress-bg">
|
|
<view class="progress-fill" :style="{width: apartmentPercent + '%', background: getProgressColor(apartmentPercent)}"></view>
|
|
</view>
|
|
</view>
|
|
<view class="usage-value">
|
|
<text>{{usageStats.usage.apartments}}/{{usageStats.limits.apartments}}</text>
|
|
</view>
|
|
</view>
|
|
<view class="usage-item">
|
|
<view class="usage-label">
|
|
<uni-icons type="shop-filled" size="16" color="#67C23A"></uni-icons>
|
|
<text>房间</text>
|
|
</view>
|
|
<view class="usage-bar">
|
|
<view class="progress-bg">
|
|
<view class="progress-fill" :style="{width: roomPercent + '%', background: getProgressColor(roomPercent)}"></view>
|
|
</view>
|
|
</view>
|
|
<view class="usage-value">
|
|
<text>{{usageStats.usage.rooms}}/{{usageStats.limits.rooms}}</text>
|
|
</view>
|
|
</view>
|
|
<view class="usage-item">
|
|
<view class="usage-label">
|
|
<uni-icons type="person-filled" size="16" color="#E6A23C"></uni-icons>
|
|
<text>用户</text>
|
|
</view>
|
|
<view class="usage-bar">
|
|
<view class="progress-bg">
|
|
<view class="progress-fill" :style="{width: userPercent + '%', background: getProgressColor(userPercent)}"></view>
|
|
</view>
|
|
</view>
|
|
<view class="usage-value">
|
|
<text>{{usageStats.usage.users}}/{{usageStats.limits.users}}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="empty-tip" v-else>
|
|
<text>暂无使用数据</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 快捷入口 -->
|
|
<view class="quick-menu">
|
|
<view class="menu-item" @click="goToPlanSelect">
|
|
<view class="menu-icon" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">
|
|
<uni-icons type="plus-filled" size="24" color="#FFFFFF"></uni-icons>
|
|
</view>
|
|
<text class="menu-text">购买套餐</text>
|
|
</view>
|
|
<view class="menu-item" @click="goToOrderList">
|
|
<view class="menu-icon" style="background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);">
|
|
<uni-icons type="list-filled" size="24" color="#FFFFFF"></uni-icons>
|
|
</view>
|
|
<text class="menu-text">我的订单</text>
|
|
</view>
|
|
<view class="menu-item" @click="goToPaymentRecord">
|
|
<view class="menu-icon" style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);">
|
|
<uni-icons type="wallet-filled" size="24" color="#FFFFFF"></uni-icons>
|
|
</view>
|
|
<text class="menu-text">支付记录</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 最近订单 -->
|
|
<view class="section-card" v-if="recentOrders.length > 0">
|
|
<view class="card-header">
|
|
<view class="header-left">
|
|
<uni-icons type="list-filled" size="20" color="#667eea"></uni-icons>
|
|
<text class="header-title">最近订单</text>
|
|
</view>
|
|
<text class="more-text" @click="goToOrderList">查看全部</text>
|
|
</view>
|
|
<view class="order-list">
|
|
<view v-for="(order, index) in recentOrders" :key="index" class="order-item" @click="viewOrderDetail(order)">
|
|
<view class="order-info">
|
|
<text class="order-no">{{order.orderNo}}</text>
|
|
<text class="order-plan">{{order.planName}}</text>
|
|
</view>
|
|
<view class="order-meta">
|
|
<text class="order-amount">¥{{order.actualAmount}}</text>
|
|
<view class="order-status" :class="order.status">{{getOrderStatusText(order.status)}}</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="safe-area-bottom" style="height: 40rpx;"></view>
|
|
</scroll-view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import { billingApi } from '@/api/index.js'
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
billingInfo: {},
|
|
usageStats: null,
|
|
recentOrders: [],
|
|
isLoading: false
|
|
}
|
|
},
|
|
computed: {
|
|
billingStatusClass() {
|
|
const status = this.billingInfo.billingStatus
|
|
if (status === 'trial_active' || status === 'paid_active') {
|
|
return 'status-normal'
|
|
} else if (status === 'trial_expired' || status === 'paid_expired') {
|
|
return 'status-expired'
|
|
}
|
|
return 'status-warning'
|
|
},
|
|
statusIcon() {
|
|
const status = this.billingInfo.billingStatus
|
|
if (status === 'trial_active') return 'gift-filled'
|
|
if (status === 'paid_active') return 'checkmarkempty'
|
|
if (status === 'trial_expired' || status === 'paid_expired') return 'info-filled'
|
|
return 'info-filled'
|
|
},
|
|
statusTitle() {
|
|
const status = this.billingInfo.billingStatus
|
|
if (status === 'trial_active') return '试用期中'
|
|
if (status === 'paid_active') return '付费使用中'
|
|
if (status === 'trial_expired') return '试用期已过期'
|
|
if (status === 'paid_expired') return '付费期已过期'
|
|
return '账户状态异常'
|
|
},
|
|
statusDesc() {
|
|
const status = this.billingInfo.billingStatus
|
|
if (status === 'trial_active') {
|
|
return `试用期将于 ${this.formatDate(this.billingInfo.trialEndDate)} 结束`
|
|
}
|
|
if (status === 'paid_active') {
|
|
return `有效期至 ${this.formatDate(this.billingInfo.paidEndDate)}`
|
|
}
|
|
if (status === 'trial_expired' || status === 'paid_expired') {
|
|
return '您的账户已过期,请尽快续费以恢复使用'
|
|
}
|
|
return '请联系客服处理'
|
|
},
|
|
needRenewal() {
|
|
const status = this.billingInfo.billingStatus
|
|
return status === 'trial_expired' || status === 'paid_expired'
|
|
},
|
|
daysLeft() {
|
|
if (!this.billingInfo) return 0
|
|
const endDate = this.billingInfo.trialEndDate || this.billingInfo.paidEndDate
|
|
if (!endDate) return 0
|
|
const end = new Date(endDate)
|
|
const now = new Date()
|
|
const diff = Math.ceil((end - now) / (1000 * 60 * 60 * 24))
|
|
return Math.max(0, diff)
|
|
},
|
|
progressPercent() {
|
|
const total = 30
|
|
return Math.min(100, Math.max(0, (this.daysLeft / total) * 100))
|
|
},
|
|
progressColor() {
|
|
if (this.daysLeft > 7) return '#67C23A'
|
|
if (this.daysLeft > 3) return '#E6A23C'
|
|
return '#F56C6C'
|
|
},
|
|
planTagType() {
|
|
const status = this.billingInfo.billingStatus
|
|
if (status === 'trial_active') return 'success'
|
|
if (status === 'paid_active') return 'primary'
|
|
if (status === 'trial_expired' || status === 'paid_expired') return 'danger'
|
|
return 'info'
|
|
},
|
|
billingInfoStatusText() {
|
|
const status = this.billingInfo.billingStatus
|
|
if (status === 'trial_active') return '试用期'
|
|
if (status === 'paid_active') return '付费期'
|
|
if (status === 'trial_expired') return '试用期已过期'
|
|
if (status === 'paid_expired') return '付费期已过期'
|
|
return '未知'
|
|
},
|
|
apartmentPercent() {
|
|
if (!this.usageStats) return 0
|
|
const { usage, limits } = this.usageStats
|
|
if (limits.apartments === 0) return 0
|
|
return Math.min(100, Math.round((usage.apartments / limits.apartments) * 100))
|
|
},
|
|
roomPercent() {
|
|
if (!this.usageStats) return 0
|
|
const { usage, limits } = this.usageStats
|
|
if (limits.rooms === 0) return 0
|
|
return Math.min(100, Math.round((usage.rooms / limits.rooms) * 100))
|
|
},
|
|
userPercent() {
|
|
if (!this.usageStats) return 0
|
|
const { usage, limits } = this.usageStats
|
|
if (limits.users === 0) return 0
|
|
return Math.min(100, Math.round((usage.users / limits.users) * 100))
|
|
}
|
|
},
|
|
onLoad() {
|
|
this.loadData()
|
|
},
|
|
onShow() {
|
|
this.loadData()
|
|
},
|
|
onPullDownRefresh() {
|
|
this.loadData().finally(() => {
|
|
uni.stopPullDownRefresh()
|
|
})
|
|
},
|
|
methods: {
|
|
async loadData() {
|
|
if (this.isLoading) return
|
|
this.isLoading = true
|
|
|
|
try {
|
|
await Promise.all([
|
|
this.loadBillingInfo(),
|
|
this.loadUsageStats(),
|
|
this.loadRecentOrders()
|
|
])
|
|
} catch (error) {
|
|
console.error('加载数据失败:', error)
|
|
} finally {
|
|
this.isLoading = false
|
|
}
|
|
},
|
|
|
|
async loadBillingInfo() {
|
|
try {
|
|
const res = await billingApi.getInfo()
|
|
if (res.code === 200) {
|
|
const { tenant, plan, usage } = res.data
|
|
this.billingInfo = {
|
|
...tenant,
|
|
plan,
|
|
usage
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('加载计费信息失败:', error)
|
|
}
|
|
},
|
|
|
|
async loadUsageStats() {
|
|
try {
|
|
const res = await billingApi.getUsage()
|
|
if (res.code === 200) {
|
|
this.usageStats = res.data
|
|
}
|
|
} catch (error) {
|
|
console.error('加载使用统计失败:', error)
|
|
}
|
|
},
|
|
|
|
async loadRecentOrders() {
|
|
try {
|
|
const res = await billingApi.getOrders({ page: 1, pageSize: 5 })
|
|
if (res.code === 200) {
|
|
this.recentOrders = res.data.list || []
|
|
}
|
|
} catch (error) {
|
|
console.error('加载订单失败:', error)
|
|
}
|
|
},
|
|
|
|
refreshData() {
|
|
this.loadData()
|
|
uni.showToast({ title: '已刷新', icon: 'success' })
|
|
},
|
|
|
|
async refreshUsage() {
|
|
await this.loadUsageStats()
|
|
uni.showToast({ title: '已刷新', icon: 'success' })
|
|
},
|
|
|
|
getProgressColor(percent) {
|
|
if (percent < 60) return '#67C23A'
|
|
if (percent < 80) return '#E6A23C'
|
|
return '#F56C6C'
|
|
},
|
|
|
|
getOrderStatusText(status) {
|
|
const map = {
|
|
pending: '待支付',
|
|
paid: '已支付',
|
|
cancelled: '已取消'
|
|
}
|
|
return map[status] || status
|
|
},
|
|
|
|
formatDate(date) {
|
|
if (!date) return '-'
|
|
return new Date(date).toLocaleDateString('zh-CN')
|
|
},
|
|
|
|
goBack() {
|
|
uni.navigateBack()
|
|
},
|
|
|
|
goToPlanSelect() {
|
|
uni.navigateTo({
|
|
url: '/pages/billing/plan-select'
|
|
})
|
|
},
|
|
|
|
goToOrderList() {
|
|
uni.navigateTo({
|
|
url: '/pages/billing/order-list'
|
|
})
|
|
},
|
|
|
|
goToPaymentRecord() {
|
|
uni.navigateTo({
|
|
url: '/pages/billing/payment-record'
|
|
})
|
|
},
|
|
|
|
viewOrderDetail(order) {
|
|
uni.navigateTo({
|
|
url: `/pages/billing/order-detail?id=${order.id}`
|
|
})
|
|
},
|
|
|
|
loadMore() {
|
|
// 加载更多订单
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.billing-center-page {
|
|
min-height: 100vh;
|
|
background: #F8FAFC;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
/* 导航栏 */
|
|
.custom-nav {
|
|
background: #FFFFFF;
|
|
border-bottom: 2rpx solid #F1F5F9;
|
|
}
|
|
|
|
.nav-content {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 20rpx 32rpx;
|
|
}
|
|
|
|
.nav-btn {
|
|
width: 72rpx;
|
|
height: 72rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.nav-title {
|
|
font-size: 34rpx;
|
|
font-weight: 600;
|
|
color: #1E293B;
|
|
}
|
|
|
|
/* 页面内容 */
|
|
.page-content {
|
|
flex: 1;
|
|
padding: 24rpx 32rpx;
|
|
}
|
|
|
|
/* 状态卡片 */
|
|
.status-card {
|
|
background: #FFFFFF;
|
|
border-radius: 24rpx;
|
|
padding: 32rpx;
|
|
margin-bottom: 24rpx;
|
|
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
|
|
border-left: 8rpx solid transparent;
|
|
}
|
|
|
|
.status-card.status-normal {
|
|
border-left-color: #67C23A;
|
|
}
|
|
|
|
.status-card.status-expired {
|
|
border-left-color: #F56C6C;
|
|
}
|
|
|
|
.status-card.status-warning {
|
|
border-left-color: #E6A23C;
|
|
}
|
|
|
|
.status-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 24rpx;
|
|
}
|
|
|
|
.status-icon {
|
|
width: 80rpx;
|
|
height: 80rpx;
|
|
border-radius: 20rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.status-normal .status-icon {
|
|
background: linear-gradient(135deg, #67C23A 0%, #85ce61 100%);
|
|
}
|
|
|
|
.status-expired .status-icon {
|
|
background: linear-gradient(135deg, #F56C6C 0%, #f78989 100%);
|
|
}
|
|
|
|
.status-warning .status-icon {
|
|
background: linear-gradient(135deg, #E6A23C 0%, #ebb563 100%);
|
|
}
|
|
|
|
.status-info {
|
|
flex: 1;
|
|
}
|
|
|
|
.status-title {
|
|
display: block;
|
|
font-size: 32rpx;
|
|
font-weight: 700;
|
|
color: #1E293B;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.status-desc {
|
|
display: block;
|
|
font-size: 26rpx;
|
|
color: #64748B;
|
|
}
|
|
|
|
.status-progress {
|
|
margin-top: 24rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 16rpx;
|
|
}
|
|
|
|
.progress-bar {
|
|
flex: 1;
|
|
height: 12rpx;
|
|
background: #F1F5F9;
|
|
border-radius: 6rpx;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.progress-fill {
|
|
height: 100%;
|
|
border-radius: 6rpx;
|
|
transition: width 0.3s ease;
|
|
}
|
|
|
|
.days-left {
|
|
font-size: 24rpx;
|
|
color: #64748B;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.status-action {
|
|
margin-top: 24rpx;
|
|
}
|
|
|
|
.renew-btn {
|
|
width: 100%;
|
|
background: linear-gradient(135deg, #F56C6C 0%, #f78989 100%);
|
|
color: #FFFFFF;
|
|
font-size: 30rpx;
|
|
font-weight: 600;
|
|
padding: 28rpx;
|
|
border-radius: 16rpx;
|
|
border: none;
|
|
}
|
|
|
|
/* 区块卡片 */
|
|
.section-card {
|
|
background: #FFFFFF;
|
|
border-radius: 24rpx;
|
|
padding: 28rpx;
|
|
margin-bottom: 24rpx;
|
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
|
|
}
|
|
|
|
.card-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 24rpx;
|
|
padding-bottom: 20rpx;
|
|
border-bottom: 2rpx solid #F1F5F9;
|
|
}
|
|
|
|
.header-left {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12rpx;
|
|
}
|
|
|
|
.header-title {
|
|
font-size: 30rpx;
|
|
font-weight: 700;
|
|
color: #1E293B;
|
|
}
|
|
|
|
.plan-tag {
|
|
padding: 8rpx 20rpx;
|
|
border-radius: 8rpx;
|
|
font-size: 24rpx;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.plan-tag.success {
|
|
background: #D1FAE5;
|
|
color: #059669;
|
|
}
|
|
|
|
.plan-tag.primary {
|
|
background: #DBEAFE;
|
|
color: #2563EB;
|
|
}
|
|
|
|
.plan-tag.danger {
|
|
background: #FEE2E2;
|
|
color: #DC2626;
|
|
}
|
|
|
|
.plan-tag.info {
|
|
background: #F3F4F6;
|
|
color: #6B7280;
|
|
}
|
|
|
|
.refresh-text, .more-text {
|
|
font-size: 26rpx;
|
|
color: #409EFF;
|
|
}
|
|
|
|
/* 套餐内容 */
|
|
.plan-content {
|
|
text-align: center;
|
|
}
|
|
|
|
.plan-main {
|
|
margin-bottom: 16rpx;
|
|
}
|
|
|
|
.plan-name {
|
|
display: block;
|
|
font-size: 36rpx;
|
|
font-weight: 700;
|
|
color: #1E293B;
|
|
margin-bottom: 12rpx;
|
|
}
|
|
|
|
.plan-price {
|
|
display: flex;
|
|
align-items: baseline;
|
|
justify-content: center;
|
|
gap: 8rpx;
|
|
}
|
|
|
|
.plan-price .price {
|
|
font-size: 48rpx;
|
|
font-weight: 700;
|
|
color: #F56C6C;
|
|
}
|
|
|
|
.plan-price .unit {
|
|
font-size: 26rpx;
|
|
color: #94A3B8;
|
|
}
|
|
|
|
.plan-desc {
|
|
display: block;
|
|
font-size: 26rpx;
|
|
color: #64748B;
|
|
margin-bottom: 24rpx;
|
|
}
|
|
|
|
.plan-resources {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 32rpx;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.resource-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8rpx;
|
|
padding: 16rpx 24rpx;
|
|
background: #F8FAFC;
|
|
border-radius: 12rpx;
|
|
font-size: 26rpx;
|
|
color: #64748B;
|
|
}
|
|
|
|
/* 资源使用 */
|
|
.usage-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 24rpx;
|
|
}
|
|
|
|
.usage-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 16rpx;
|
|
}
|
|
|
|
.usage-label {
|
|
width: 100rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8rpx;
|
|
font-size: 26rpx;
|
|
color: #64748B;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.usage-bar {
|
|
flex: 1;
|
|
}
|
|
|
|
.progress-bg {
|
|
height: 12rpx;
|
|
background: #F1F5F9;
|
|
border-radius: 6rpx;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.usage-value {
|
|
width: 100rpx;
|
|
text-align: right;
|
|
font-size: 24rpx;
|
|
color: #64748B;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* 快捷菜单 */
|
|
.quick-menu {
|
|
display: flex;
|
|
justify-content: space-around;
|
|
background: #FFFFFF;
|
|
border-radius: 24rpx;
|
|
padding: 32rpx;
|
|
margin-bottom: 24rpx;
|
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
|
|
}
|
|
|
|
.menu-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 16rpx;
|
|
}
|
|
|
|
.menu-icon {
|
|
width: 100rpx;
|
|
height: 100rpx;
|
|
border-radius: 24rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.menu-text {
|
|
font-size: 26rpx;
|
|
color: #64748B;
|
|
}
|
|
|
|
/* 订单列表 */
|
|
.order-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.order-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 24rpx 0;
|
|
border-bottom: 2rpx solid #F1F5F9;
|
|
}
|
|
|
|
.order-item:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.order-info {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8rpx;
|
|
}
|
|
|
|
.order-no {
|
|
font-size: 28rpx;
|
|
font-weight: 600;
|
|
color: #1E293B;
|
|
}
|
|
|
|
.order-plan {
|
|
font-size: 24rpx;
|
|
color: #64748B;
|
|
}
|
|
|
|
.order-meta {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: flex-end;
|
|
gap: 8rpx;
|
|
}
|
|
|
|
.order-amount {
|
|
font-size: 30rpx;
|
|
font-weight: 700;
|
|
color: #F56C6C;
|
|
}
|
|
|
|
.order-status {
|
|
padding: 6rpx 16rpx;
|
|
border-radius: 8rpx;
|
|
font-size: 22rpx;
|
|
}
|
|
|
|
.order-status.pending {
|
|
background: #FEF3C7;
|
|
color: #D97706;
|
|
}
|
|
|
|
.order-status.paid {
|
|
background: #D1FAE5;
|
|
color: #059669;
|
|
}
|
|
|
|
.order-status.cancelled {
|
|
background: #F3F4F6;
|
|
color: #6B7280;
|
|
}
|
|
|
|
/* 空提示 */
|
|
.empty-tip {
|
|
text-align: center;
|
|
padding: 48rpx 0;
|
|
color: #94A3B8;
|
|
font-size: 28rpx;
|
|
}
|
|
</style>
|