741 lines
20 KiB
Plaintext
741 lines
20 KiB
Plaintext
<!-- 消费者端 - 订单详情页 -->
|
||
<template>
|
||
<view class="order-detail-page">
|
||
<scroll-view scroll-y="true" class="scroll-content">
|
||
<!-- 订单状态 -->
|
||
<view class="order-status" :class="getStatusClass()">
|
||
<view class="status-icon">
|
||
<text class="status-emoji">{{ getStatusIcon() }}</text>
|
||
</view>
|
||
<view class="status-info">
|
||
<text class="status-text">{{ getStatusText() }}</text>
|
||
<text class="status-desc">{{ getStatusDesc() }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 配送信息 -->
|
||
<view v-if="order != null && (order?.order_status ?? 0) >= 2" class="delivery-info card">
|
||
<view class="delivery-header">
|
||
<text class="section-title">配送信息</text>
|
||
</view>
|
||
<view class="delivery-address">
|
||
<view class="address-icon">📍</view>
|
||
<view class="address-content">
|
||
<view class="address-user">
|
||
<text class="recipient">{{ deliveryAddress?.name ?? '' }}</text>
|
||
<text class="phone">{{ deliveryAddress?.phone ?? '' }}</text>
|
||
</view>
|
||
<text class="address-detail">{{ getFullAddress(deliveryAddress as any) }}</text>
|
||
</view>
|
||
</view>
|
||
<!-- 如果有物流信息显示 -->
|
||
<view v-if="deliveryInfo != null && deliveryInfo?.tracking_no != ''" class="courier-info">
|
||
<text class="courier-label">物流单号:</text>
|
||
<text class="courier-value">{{ deliveryInfo?.tracking_no ?? '' }}</text>
|
||
<text class="copy-btn" @click="copyText(deliveryInfo?.tracking_no ?? '')">复制</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 商品信息 -->
|
||
<view class="order-products card">
|
||
<view class="shop-header" @click="goToShop">
|
||
<text class="shop-icon">🏪</text>
|
||
<text class="shop-name">{{ shopName }}</text>
|
||
<text class="arrow-right">></text>
|
||
</view>
|
||
<view v-for="item in orderItems" :key="item.id" class="product-item" @click="goToProduct(item.product_id)">
|
||
<image :src="item.image_url != null && item.image_url != '' ? item.image_url : '/static/default-product.png'" class="product-image" mode="aspectFill"/>
|
||
<view class="product-info">
|
||
<text class="product-name">{{ item.product_name }}</text>
|
||
<text v-if="item.specifications" class="product-spec">{{ getSpecText(item.specifications) }}</text>
|
||
<view class="price-quantity">
|
||
<text class="product-price">¥{{ item.price }}</text>
|
||
<text class="product-quantity">×{{ item.quantity }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 订单信息 -->
|
||
<view class="order-info card" v-if="order != null">
|
||
<view class="info-row">
|
||
<text class="info-label">订单编号</text>
|
||
<text class="info-value copyable" @click="copyText(order?.order_no ?? '')">{{ order?.order_no ?? '' }} <text class="copy-icon">📄</text></text>
|
||
</view>
|
||
<view class="info-row">
|
||
<text class="info-label">下单时间</text>
|
||
<text class="info-value">{{ formatTime(order?.created_at ?? '') }}</text>
|
||
</view>
|
||
<view class="info-row" v-if="order?.payment_method != null && order?.payment_method != ''">
|
||
<text class="info-label">支付方式</text>
|
||
<text class="info-value">{{ getPaymentMethodText(order?.payment_method as any) }}</text>
|
||
</view>
|
||
<view class="info-row" v-if="order?.paid_at != null && order?.paid_at != ''">
|
||
<text class="info-label">支付时间</text>
|
||
<text class="info-value">{{ formatTime(order?.paid_at ?? '') }}</text>
|
||
</view>
|
||
<view class="info-row" v-if="order?.shipped_at != null && order?.shipped_at != ''">
|
||
<text class="info-label">发货时间</text>
|
||
<text class="info-value">{{ formatTime(order?.shipped_at ?? '') }}</text>
|
||
</view>
|
||
<view class="info-row" v-if="order?.completed_at != null && order?.completed_at != ''">
|
||
<text class="info-label">完成时间</text>
|
||
<text class="info-value">{{ formatTime(order?.completed_at ?? '') }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 费用明细 -->
|
||
<view class="cost-detail card" v-if="order != null">
|
||
<view class="cost-row">
|
||
<text class="cost-label">商品总额</text>
|
||
<text class="cost-value">¥{{ order?.product_amount ?? 0 }}</text>
|
||
</view>
|
||
<view class="cost-row">
|
||
<text class="cost-label">运费</text>
|
||
<text class="cost-value">+¥{{ order?.shipping_fee != null ? order?.shipping_fee : 0 }}</text>
|
||
</view>
|
||
<view class="cost-row" v-if="(order?.discount_amount ?? 0) > 0">
|
||
<text class="cost-label">优惠金额</text>
|
||
<text class="cost-value">-¥{{ order?.discount_amount ?? 0 }}</text>
|
||
</view>
|
||
<view class="cost-row total">
|
||
<text class="cost-label">实付金额</text>
|
||
<text class="cost-value price">¥{{ order?.total_amount ?? 0 }}</text>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
|
||
<!-- 底部操作 -->
|
||
<view class="bottom-actions" v-if="order != null">
|
||
<view class="action-left">
|
||
<view class="service-btn" @click="contactService">
|
||
<text class="service-icon">🎧</text>
|
||
<text>客服</text>
|
||
</view>
|
||
</view>
|
||
<view class="action-right">
|
||
<button v-if="order?.order_status === 1" class="btn primary" @click="payOrder">立即支付</button>
|
||
<button v-if="order?.order_status === 1" class="btn" @click="cancelOrder">取消订单</button>
|
||
|
||
<button v-if="order?.order_status === 2" class="btn" @click="remindDelivery">提醒发货</button>
|
||
<button v-if="order?.order_status === 2" class="btn" @click="applyRefund">申请退款</button>
|
||
|
||
<button v-if="order?.order_status === 3" class="btn primary" @click="confirmReceive">确认收货</button>
|
||
<button v-if="order?.order_status === 3" class="btn" @click="viewLogistics">查看物流</button>
|
||
|
||
<button v-if="order?.order_status === 4" class="btn primary" @click="goToReview">评价</button>
|
||
<button v-if="order?.order_status === 4" class="btn" @click="rePurchase">再次购买</button>
|
||
<button v-if="order?.order_status === 4" class="btn" @click="applyAfterSales">申请售后</button>
|
||
|
||
<button v-if="order?.order_status === 5" class="btn" @click="rePurchase">重新购买</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="uts">
|
||
import { ref, onMounted, computed } from 'vue'
|
||
import { onLoad } from '@dcloudio/uni-app'
|
||
import { supabaseService } from '@/utils/supabaseService.uts'
|
||
import supa from '@/components/supadb/aksupainstance.uts'
|
||
|
||
// 定义订单类型
|
||
type OrderType = {
|
||
order_no: string,
|
||
order_status: number,
|
||
total_amount: number,
|
||
product_amount: number,
|
||
shipping_fee: number,
|
||
discount_amount: number,
|
||
payment_method: string,
|
||
created_at: string,
|
||
paid_at: string,
|
||
shipped_at: string,
|
||
completed_at: string,
|
||
merchant_id: string,
|
||
shipping_address: any
|
||
}
|
||
|
||
type OrderItemType = {
|
||
id: string,
|
||
product_id: string,
|
||
product_name: string,
|
||
image_url: string,
|
||
price: number,
|
||
quantity: number,
|
||
specifications: any
|
||
}
|
||
|
||
type AddressType = {
|
||
name: string,
|
||
phone: string,
|
||
province: string,
|
||
city: string,
|
||
district: string,
|
||
detail: string,
|
||
address: string
|
||
}
|
||
|
||
type DeliveryInfoType = {
|
||
tracking_no: string
|
||
}
|
||
|
||
const orderId = ref('')
|
||
const order = ref<OrderType | null>(null)
|
||
const orderItems = ref<OrderItemType[]>([])
|
||
const shopName = ref('店铺名称')
|
||
const deliveryAddress = ref<AddressType | null>(null)
|
||
const deliveryInfo = ref<DeliveryInfoType | null>(null)
|
||
|
||
// 辅助函数 - 必须在调用前定义
|
||
const getStatusText = (): string => {
|
||
const status = order.value?.order_status ?? 0
|
||
if (status == 1) return '待付款'
|
||
if (status == 2) return '待发货'
|
||
if (status == 3) return '待收货'
|
||
if (status == 4) return '已完成'
|
||
if (status == 5) return '已取消'
|
||
if (status == 6) return '退款中'
|
||
if (status == 7) return '已退款'
|
||
return '未知状态'
|
||
}
|
||
|
||
const getStatusDesc = (): string => {
|
||
const status = order.value?.order_status ?? 0
|
||
if (status == 1) return '请尽快完成支付'
|
||
if (status == 2) return '商家正在打包商品'
|
||
if (status == 3) return '商品正在赶往您的地址'
|
||
if (status == 4) return '订单已完成,感谢支持'
|
||
if (status == 5) return '订单已取消'
|
||
if (status == 6) return '售后处理中'
|
||
if (status == 7) return '钱款已退回'
|
||
return ''
|
||
}
|
||
|
||
const getStatusIcon = (): string => {
|
||
const status = order.value?.order_status ?? 0
|
||
if (status === 1) return '💳'
|
||
if (status === 2) return '📦'
|
||
if (status === 3) return '🚚'
|
||
if (status === 4) return '✅'
|
||
return '📝'
|
||
}
|
||
|
||
const getStatusClass = (): string => {
|
||
const status = order.value?.order_status ?? 0
|
||
return `status-${status}`
|
||
}
|
||
|
||
const getFullAddress = (addr: any): string => {
|
||
if (addr == null) return ''
|
||
// 兼容简单的字符串地址和对象地址
|
||
if (typeof addr === 'string') return addr
|
||
const addrObj = addr as Record<string, any>
|
||
if (addrObj['address'] != null) return addrObj['address'] as string
|
||
return ((addrObj['province'] as string) ?? '') + ((addrObj['city'] as string) ?? '') + ((addrObj['district'] as string) ?? '') + ((addrObj['detail'] as string) ?? (addrObj['address_detail'] as string) ?? '')
|
||
}
|
||
|
||
const getSpecText = (specs: any): string => {
|
||
if (specs == null) return ''
|
||
if (typeof specs === 'string') return specs
|
||
// 简化处理:直接返回字符串形式
|
||
return JSON.stringify(specs)
|
||
}
|
||
|
||
const formatTime = (iso: string): string => {
|
||
if (iso == '') return ''
|
||
const d = new Date(iso)
|
||
return `${d.getFullYear()}-${d.getMonth()+1}-${d.getDate()} ${d.getHours()}:${d.getMinutes()}`
|
||
}
|
||
|
||
const getPaymentMethodText = (method: any): string => {
|
||
return '在线支付'
|
||
}
|
||
|
||
const copyText = (text: string) => {
|
||
if(text == '') return
|
||
uni.setClipboardData({
|
||
data: text,
|
||
success: () => uni.showToast({ title: '已复制' })
|
||
})
|
||
}
|
||
|
||
const loadShopInfo = async (merchantId: string) => {
|
||
const result = await supa
|
||
.from('ml_shops')
|
||
.select('shop_name')
|
||
.eq('merchant_id', merchantId)
|
||
.single()
|
||
const resultObj = result as Record<string, any>
|
||
const resultData = resultObj['data']
|
||
if (resultData != null) {
|
||
const dataObj = resultData as Record<string, any>
|
||
shopName.value = dataObj['shop_name'] as string
|
||
}
|
||
}
|
||
|
||
const loadOrderDetail = async () => {
|
||
uni.showLoading({ title: '加载中' })
|
||
try {
|
||
const data = await supabaseService.getOrderDetail(orderId.value)
|
||
if (data != null) {
|
||
const dataObj = data as Record<string, any>
|
||
order.value = data as OrderType
|
||
const items = dataObj['ml_order_items']
|
||
orderItems.value = items != null ? (items as OrderItemType[]) : []
|
||
deliveryAddress.value = dataObj['shipping_address'] as AddressType
|
||
|
||
// 获取店铺信息
|
||
const merchantId = dataObj['merchant_id'] as string
|
||
if (merchantId != null && merchantId != '') {
|
||
loadShopInfo(merchantId)
|
||
}
|
||
} else {
|
||
uni.showToast({ title: '订单不存在', icon: 'none' })
|
||
}
|
||
} catch (e) {
|
||
uni.showToast({ title: '加载失败', icon: 'none' })
|
||
} finally {
|
||
uni.hideLoading()
|
||
}
|
||
}
|
||
|
||
// 动作函数
|
||
const contactService = () => {
|
||
uni.showActionSheet({
|
||
itemList: ['在线客服', '拨打电话'],
|
||
success: (res) => {
|
||
if (res.tapIndex === 1) {
|
||
// 模拟拨打电话
|
||
uni.makePhoneCall({ phoneNumber: '400-123-4567' })
|
||
} else {
|
||
uni.showToast({ title: '连接到了商家客服' })
|
||
// 这里可以跳转到聊天页面
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
const payOrder = () => {
|
||
const totalAmount = order.value?.total_amount ?? 0
|
||
uni.navigateTo({
|
||
url: `/pages/mall/consumer/payment?orderId=${orderId.value}&amount=${totalAmount}`
|
||
})
|
||
}
|
||
|
||
const doCancelOrder = async () => {
|
||
const result = await supa.from('ml_orders').update({ order_status: 5 }).eq('id', orderId.value)
|
||
const resultObj = result as Record<string, any>
|
||
const resultError = resultObj['error']
|
||
if(resultError == null) {
|
||
if (order.value != null) {
|
||
order.value.order_status = 5
|
||
}
|
||
uni.showToast({ title: '订单已取消' })
|
||
}
|
||
}
|
||
|
||
const cancelOrder = () => {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '确定要取消订单吗?',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
doCancelOrder()
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
const remindDelivery = () => {
|
||
uni.showToast({ title: '已提醒商家尽快发货' })
|
||
}
|
||
|
||
const viewLogistics = () => {
|
||
uni.navigateTo({ url: `/pages/mall/consumer/logistics?orderId=${orderId.value}` })
|
||
}
|
||
|
||
const goToReview = () => {
|
||
uni.navigateTo({ url: `/pages/mall/consumer/review?orderId=${orderId.value}` })
|
||
}
|
||
|
||
const doConfirmReceive = async () => {
|
||
const result = await supabaseService.confirmReceipt(orderId.value)
|
||
if (result.success) {
|
||
if (order.value != null) {
|
||
order.value.order_status = 4
|
||
}
|
||
uni.showToast({ title: '收货成功' })
|
||
setTimeout(() => goToReview(), 1500)
|
||
} else {
|
||
uni.showToast({ title: result.error ?? '失败', icon: 'none' })
|
||
}
|
||
}
|
||
|
||
const confirmReceive = () => {
|
||
uni.showModal({
|
||
title: '确认收货',
|
||
content: '确保您已收到货物',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
doConfirmReceive()
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
const rePurchase = async () => {
|
||
uni.showLoading({ title: '处理中' })
|
||
const orderData = order.value as any
|
||
const success = await supabaseService.rePurchase(orderData)
|
||
uni.hideLoading()
|
||
if (success) {
|
||
uni.showToast({ title: '已加入购物车' })
|
||
setTimeout(() => {
|
||
uni.switchTab({ url: '/pages/mall/consumer/cart' })
|
||
}, 1000)
|
||
} else {
|
||
uni.showToast({ title: '操作失败', icon: 'none' })
|
||
}
|
||
}
|
||
|
||
const doApplyRefund = async (reason: string) => {
|
||
const success = await supabaseService.applyRefund(orderId.value, reason)
|
||
if (success) {
|
||
if (order.value != null) {
|
||
order.value.order_status = 6
|
||
}
|
||
uni.showToast({ title: '申请已提交' })
|
||
} else {
|
||
uni.showToast({ title: '提交失败', icon: 'none' })
|
||
}
|
||
}
|
||
|
||
const applyRefund = () => {
|
||
uni.showModal({
|
||
title: '申请退款',
|
||
editable: true,
|
||
placeholderText: '请输入退款原因',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
const reason = res.content ?? '用户主动申请'
|
||
doApplyRefund(reason)
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
const applyAfterSales = () => {
|
||
// 售后逻辑类似退款,或者是跳转到专门的售后单页面
|
||
applyRefund()
|
||
}
|
||
|
||
const goToShop = () => {
|
||
// 跳转到店铺详情
|
||
// uni.navigateTo({ url: `/pages/mall/shop/index?id=${order.value.merchant_id}` })
|
||
uni.showToast({ title: '进入店铺: ' + shopName.value })
|
||
}
|
||
|
||
const goToProduct = (pid: string) => {
|
||
uni.navigateTo({ url: `/pages/mall/consumer/product-detail?id=${pid}` })
|
||
}
|
||
|
||
// 生命周期 - 在所有函数定义之后
|
||
onLoad((options) => {
|
||
const id = options['id']
|
||
const orderIdParam = options['orderId']
|
||
if (id != null && id != '') {
|
||
orderId.value = id as string
|
||
loadOrderDetail()
|
||
} else if (orderIdParam != null && orderIdParam != '') {
|
||
orderId.value = orderIdParam as string
|
||
loadOrderDetail()
|
||
}
|
||
})
|
||
|
||
</script>
|
||
|
||
<style scoped>
|
||
.order-detail-page {
|
||
display: flex;
|
||
flex-direction: column;
|
||
flex: 1;
|
||
background-color: #f5f5f5;
|
||
}
|
||
|
||
.scroll-content {
|
||
flex: 1;
|
||
padding-bottom: 20px;
|
||
}
|
||
|
||
.card {
|
||
background-color: #ffffff;
|
||
margin: 10px;
|
||
padding: 15px;
|
||
border-radius: 10px;
|
||
}
|
||
|
||
/* 状态栏 */
|
||
.order-status {
|
||
background: linear-gradient(to right, #ff9000, #ff5000);
|
||
padding: 20px 25px;
|
||
color: white;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.status-emoji {
|
||
font-size: 32px;
|
||
margin-right: 15px;
|
||
}
|
||
|
||
.status-text {
|
||
font-size: 18px;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.status-desc {
|
||
font-size: 12px;
|
||
opacity: 0.9;
|
||
margin-top: 5px;
|
||
}
|
||
|
||
/* 配送信息 */
|
||
.section-title {
|
||
font-weight: bold;
|
||
font-size: 16px;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.delivery-address {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
}
|
||
|
||
.address-icon {
|
||
font-size: 20px;
|
||
margin-right: 10px;
|
||
color: #666;
|
||
}
|
||
|
||
.address-user {
|
||
margin-bottom: 5px;
|
||
font-weight: bold;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.phone {
|
||
margin-left: 10px;
|
||
color: #666;
|
||
font-weight: normal;
|
||
}
|
||
|
||
.address-detail {
|
||
font-size: 13px;
|
||
color: #333;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.courier-info {
|
||
margin-top: 10px;
|
||
padding-top: 10px;
|
||
border-top: 1px solid #eee;
|
||
font-size: 13px;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.copy-btn {
|
||
margin-left: 10px;
|
||
color: #ff5000;
|
||
font-size: 12px;
|
||
border: 1px solid #ff5000;
|
||
padding: 1px 6px;
|
||
border-radius: 10px;
|
||
}
|
||
|
||
/* 店铺与商品 */
|
||
.shop-header {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 15px;
|
||
padding-bottom: 10px;
|
||
border-bottom: 1px solid #f5f5f5;
|
||
}
|
||
|
||
.shop-icon {
|
||
margin-right: 5px;
|
||
}
|
||
|
||
.shop-name {
|
||
font-size: 14px;
|
||
font-weight: bold;
|
||
flex: 1;
|
||
}
|
||
|
||
.arrow-right {
|
||
color: #999;
|
||
}
|
||
|
||
.product-item {
|
||
display: flex;
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.product-item:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.product-image {
|
||
width: 80px;
|
||
height: 80px;
|
||
border-radius: 6px;
|
||
margin-right: 10px;
|
||
background-color: #f9f9f9;
|
||
}
|
||
|
||
.product-info {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.product-name {
|
||
font-size: 14px;
|
||
line-height: 1.4;
|
||
color: #333;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
lines: 2; /* uvue specific */
|
||
}
|
||
|
||
.product-spec {
|
||
font-size: 12px;
|
||
color: #999;
|
||
background-color: #f5f5f5;
|
||
padding: 2px 5px;
|
||
border-radius: 4px;
|
||
align-self: flex-start;
|
||
margin-top: 5px;
|
||
}
|
||
|
||
.price-quantity {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-top: 5px;
|
||
}
|
||
|
||
.product-price {
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
color: #333;
|
||
}
|
||
|
||
.product-quantity {
|
||
color: #999;
|
||
font-size: 12px;
|
||
}
|
||
|
||
/* 订单详情 */
|
||
.info-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-bottom: 10px;
|
||
font-size: 13px;
|
||
}
|
||
|
||
.info-label {
|
||
color: #999;
|
||
}
|
||
|
||
.info-value {
|
||
color: #333;
|
||
}
|
||
|
||
.copy-icon {
|
||
font-size: 12px;
|
||
}
|
||
|
||
/* 费用明细 */
|
||
.cost-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-bottom: 8px;
|
||
font-size: 13px;
|
||
}
|
||
|
||
.cost-row.total {
|
||
margin-top: 15px;
|
||
padding-top: 15px;
|
||
border-top: 1px solid #f5f5f5;
|
||
align-items: center;
|
||
}
|
||
|
||
.cost-value.price {
|
||
color: #ff5000;
|
||
font-size: 18px;
|
||
font-weight: bold;
|
||
}
|
||
|
||
/* 底部按钮 */
|
||
.bottom-actions {
|
||
background-color: #ffffff;
|
||
padding: 10px 15px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
box-shadow: 0 -2px 10px rgba(0,0,0,0.05);
|
||
padding-bottom: 30px;
|
||
}
|
||
|
||
.action-left {
|
||
display: flex;
|
||
}
|
||
|
||
.service-btn {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
font-size: 10px;
|
||
color: #666;
|
||
background-color: transparent;
|
||
line-height: 1.2;
|
||
}
|
||
|
||
.service-icon {
|
||
font-size: 18px;
|
||
margin-bottom: 2px;
|
||
}
|
||
|
||
.action-right {
|
||
display: flex;
|
||
}
|
||
|
||
/* Add margin to buttons inside action-right for spacing */
|
||
.action-right .btn {
|
||
margin-left: 10px;
|
||
}
|
||
|
||
.btn {
|
||
margin: 0;
|
||
padding: 0 15px;
|
||
height: 32px;
|
||
line-height: 30px;
|
||
font-size: 13px;
|
||
border-radius: 16px;
|
||
background: #ffffff;
|
||
border: 1px solid #cccccc;
|
||
color: #666;
|
||
}
|
||
|
||
.btn.primary {
|
||
border-color: #ff5000;
|
||
color: #ff5000;
|
||
background-color: #fff0ec;
|
||
}
|
||
|
||
/* 状态样式 */
|
||
.status-4 .status-text { /* Completed */ }
|
||
</style> |