|
|
@@ -1,11 +1,12 @@
|
|
|
-import { View, ScrollView, Text } from '@tarojs/components'
|
|
|
+import { View, ScrollView, Text, Image } from '@tarojs/components'
|
|
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
|
|
import Taro from '@tarojs/taro'
|
|
|
import { orderClient } from '@/api'
|
|
|
import { InferResponseType } from 'hono'
|
|
|
import { Navbar } from '@/components/ui/navbar'
|
|
|
-import { Card } from '@/components/ui/card'
|
|
|
-import { Button } from '@/components/ui/button'
|
|
|
+import OrderCard from '@/components/order/OrderCard'
|
|
|
+import OrderButtonBar from '@/components/order/OrderButtonBar'
|
|
|
+import './index.css'
|
|
|
|
|
|
type OrderResponse = InferResponseType<typeof orderClient[':id']['$get'], 200>
|
|
|
|
|
|
@@ -103,217 +104,168 @@ export default function OrderDetailPage() {
|
|
|
)
|
|
|
}
|
|
|
|
|
|
+ // 获取订单状态描述
|
|
|
+ const getOrderStatusText = () => {
|
|
|
+ if (order.payState === 0) return '待付款'
|
|
|
+ if (order.state === 0) return '待发货'
|
|
|
+ if (order.state === 1) return '待收货'
|
|
|
+ if (order.state === 2) return '已完成'
|
|
|
+ return '已取消'
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取订单状态描述详情
|
|
|
+ const getOrderStatusDesc = () => {
|
|
|
+ if (order.payState === 0) return '请尽快完成支付'
|
|
|
+ if (order.state === 0) return '商家正在备货中'
|
|
|
+ if (order.state === 1) return '商品已发货,请注意查收'
|
|
|
+ if (order.state === 2) return '订单已完成'
|
|
|
+ return '订单已取消'
|
|
|
+ }
|
|
|
+
|
|
|
+ // 复制订单编号
|
|
|
+ const handleCopyOrderNo = () => {
|
|
|
+ Taro.setClipboardData({
|
|
|
+ data: order.orderNo,
|
|
|
+ success: () => {
|
|
|
+ Taro.showToast({
|
|
|
+ title: '订单号已复制',
|
|
|
+ icon: 'success'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
return (
|
|
|
- <View className="min-h-screen bg-gray-50">
|
|
|
+ <View className="order-detail-page">
|
|
|
<Navbar
|
|
|
title="订单详情"
|
|
|
leftIcon="i-heroicons-chevron-left-20-solid"
|
|
|
onClickLeft={() => Taro.navigateBack()}
|
|
|
/>
|
|
|
-
|
|
|
- <ScrollView className="flex-1 pt-4 pb-20">
|
|
|
- <View className="px-4 space-y-4">
|
|
|
- {/* 订单状态 */}
|
|
|
- <Card>
|
|
|
- <View className="p-4">
|
|
|
- <Text className="text-lg font-bold mb-2">订单状态</Text>
|
|
|
- <View className="flex justify-between items-center">
|
|
|
- <Text className="text-lg font-medium text-blue-500">
|
|
|
- {order.payState === 0 ? '待付款' :
|
|
|
- order.state === 0 ? '待发货' :
|
|
|
- order.state === 1 ? '待收货' :
|
|
|
- order.state === 2 ? '已完成' : '已取消'}
|
|
|
- </Text>
|
|
|
- <Text className="text-sm text-gray-500">
|
|
|
- 订单号: {order.orderNo}
|
|
|
- </Text>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
- </Card>
|
|
|
|
|
|
- {/* 收货信息 */}
|
|
|
- <Card>
|
|
|
- <View className="p-4">
|
|
|
- <Text className="text-lg font-bold mb-3">收货信息</Text>
|
|
|
- <View>
|
|
|
- <Text className="font-medium">{order.recevierName}</Text>
|
|
|
- <Text className="text-sm text-gray-600">{order.receiverMobile}</Text>
|
|
|
- <Text className="text-sm text-gray-600 mt-1">{order.address}</Text>
|
|
|
+ <ScrollView
|
|
|
+ className="refresh-container"
|
|
|
+ scrollY
|
|
|
+ refresherEnabled={true}
|
|
|
+ refresherTriggered={false}
|
|
|
+ onRefresherRefresh={() => {
|
|
|
+ // 下拉刷新逻辑
|
|
|
+ queryClient.invalidateQueries({ queryKey: ['order', orderId] })
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {/* 顶部状态卡片 */}
|
|
|
+ <View className="order-status-header">
|
|
|
+ <Text className="order-status-text">{getOrderStatusText()}</Text>
|
|
|
+ <Text className="order-status-desc">{getOrderStatusDesc()}</Text>
|
|
|
+ </View>
|
|
|
+
|
|
|
+ {/* 内容区域 */}
|
|
|
+ <View className="order-content">
|
|
|
+ {/* 收货地址区域 */}
|
|
|
+ <View className="order-section">
|
|
|
+ <View className="order-section-header">收货信息</View>
|
|
|
+ <View className="order-section-body">
|
|
|
+ <View className="address-section">
|
|
|
+ <View className="address-icon">📍</View>
|
|
|
+ <View className="address-info">
|
|
|
+ <Text className="address-receiver">
|
|
|
+ {order.recevierName} {order.receiverMobile}
|
|
|
+ </Text>
|
|
|
+ <Text className="address-detail">{order.address}</Text>
|
|
|
+ </View>
|
|
|
+ <View className="address-edit" onClick={() => {
|
|
|
+ Taro.showToast({
|
|
|
+ title: '地址修改功能开发中',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ }}>
|
|
|
+ 修改
|
|
|
+ </View>
|
|
|
</View>
|
|
|
</View>
|
|
|
- </Card>
|
|
|
+ </View>
|
|
|
|
|
|
{/* 商品列表 */}
|
|
|
- <Card>
|
|
|
- <View className="p-4">
|
|
|
- <Text className="text-lg font-bold mb-4">商品信息</Text>
|
|
|
+ <View className="order-section">
|
|
|
+ <View className="order-section-header">商品信息</View>
|
|
|
+ <View className="order-section-body">
|
|
|
{goods.map((item: any, index: number) => (
|
|
|
- <View key={index} className="flex items-center py-3 border-b border-gray-100 last:border-b-0">
|
|
|
- <img
|
|
|
+ <View key={index} className="goods-card">
|
|
|
+ <Image
|
|
|
src={item.image || ''}
|
|
|
- className="w-16 h-16 rounded-lg mr-3"
|
|
|
+ className="goods-image"
|
|
|
mode="aspectFill"
|
|
|
/>
|
|
|
- <View className="flex-1">
|
|
|
- <Text className="text-sm font-medium">{item.name}</Text>
|
|
|
- <Text className="text-sm text-gray-500">
|
|
|
- ¥{item.price.toFixed(2)} × {item.num}
|
|
|
- </Text>
|
|
|
+ <View className="goods-info">
|
|
|
+ <Text className="goods-name">{item.name}</Text>
|
|
|
+ <Text className="goods-spec">{item.spec || '默认规格'}</Text>
|
|
|
+ <View className="flex justify-between items-center mt-2">
|
|
|
+ <Text className="goods-price">¥{item.price.toFixed(2)}</Text>
|
|
|
+ <Text className="goods-quantity">×{item.num}</Text>
|
|
|
+ </View>
|
|
|
</View>
|
|
|
- <Text className="text-red-500 font-bold">
|
|
|
- ¥{(item.price * item.num).toFixed(2)}
|
|
|
- </Text>
|
|
|
</View>
|
|
|
))}
|
|
|
</View>
|
|
|
- </Card>
|
|
|
+ </View>
|
|
|
|
|
|
- {/* 订单金额 */}
|
|
|
- <Card>
|
|
|
- <View className="p-4">
|
|
|
- <Text className="text-lg font-bold mb-4">订单金额</Text>
|
|
|
- <View className="space-y-2">
|
|
|
- <View className="flex justify-between">
|
|
|
- <Text className="text-gray-600">商品总价</Text>
|
|
|
- <Text>¥{order.amount.toFixed(2)}</Text>
|
|
|
- </View>
|
|
|
- <View className="flex justify-between">
|
|
|
- <Text className="text-gray-600">运费</Text>
|
|
|
- <Text>¥{order.freightAmount.toFixed(2)}</Text>
|
|
|
- </View>
|
|
|
- <View className="flex justify-between">
|
|
|
- <Text className="text-gray-600">优惠</Text>
|
|
|
- <Text>-¥{order.discountAmount.toFixed(2)}</Text>
|
|
|
- </View>
|
|
|
- <View className="flex justify-between text-lg font-bold border-t pt-2">
|
|
|
- <Text>实付款</Text>
|
|
|
- <Text className="text-red-500">¥{order.payAmount.toFixed(2)}</Text>
|
|
|
- </View>
|
|
|
+ {/* 支付详情 */}
|
|
|
+ <View className="order-section">
|
|
|
+ <View className="order-section-header">支付详情</View>
|
|
|
+ <View className="order-section-body">
|
|
|
+ <View className="pay-detail-item">
|
|
|
+ <Text className="pay-detail-label">商品总价</Text>
|
|
|
+ <Text className="pay-detail-value">¥{order.amount.toFixed(2)}</Text>
|
|
|
+ </View>
|
|
|
+ <View className="pay-detail-item">
|
|
|
+ <Text className="pay-detail-label">运费</Text>
|
|
|
+ <Text className="pay-detail-value">¥{order.freightAmount.toFixed(2)}</Text>
|
|
|
+ </View>
|
|
|
+ <View className="pay-detail-item">
|
|
|
+ <Text className="pay-detail-label">优惠</Text>
|
|
|
+ <Text className="pay-detail-value">-¥{order.discountAmount.toFixed(2)}</Text>
|
|
|
+ </View>
|
|
|
+ <View className="pay-detail-item pay-detail-total">
|
|
|
+ <Text className="pay-detail-label">实付款</Text>
|
|
|
+ <Text className="pay-detail-value">¥{order.payAmount.toFixed(2)}</Text>
|
|
|
</View>
|
|
|
</View>
|
|
|
- </Card>
|
|
|
+ </View>
|
|
|
|
|
|
{/* 订单信息 */}
|
|
|
- <Card>
|
|
|
- <View className="p-4">
|
|
|
- <Text className="text-lg font-bold mb-4">订单信息</Text>
|
|
|
- <View className="space-y-2 text-sm">
|
|
|
- <View className="flex justify-between">
|
|
|
- <Text className="text-gray-600">订单编号</Text>
|
|
|
- <Text>{order.orderNo}</Text>
|
|
|
- </View>
|
|
|
- <View className="flex justify-between">
|
|
|
- <Text className="text-gray-600">创建时间</Text>
|
|
|
- <Text>{new Date(order.createdAt).toLocaleString()}</Text>
|
|
|
- </View>
|
|
|
- {order.payState === 2 && (
|
|
|
- <View className="flex justify-between">
|
|
|
- <Text className="text-gray-600">支付时间</Text>
|
|
|
- <Text>{new Date(order.createdAt).toLocaleString()}</Text>
|
|
|
+ <View className="order-section">
|
|
|
+ <View className="order-section-header">订单信息</View>
|
|
|
+ <View className="order-section-body">
|
|
|
+ <View className="order-info-item">
|
|
|
+ <Text className="order-info-label">订单编号</Text>
|
|
|
+ <View className="flex items-center">
|
|
|
+ <Text className="order-info-value">{order.orderNo}</Text>
|
|
|
+ <View className="order-copy-btn" onClick={handleCopyOrderNo}>
|
|
|
+ 复制
|
|
|
</View>
|
|
|
- )}
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ <View className="order-info-item">
|
|
|
+ <Text className="order-info-label">创建时间</Text>
|
|
|
+ <Text className="order-info-value">{new Date(order.createdAt).toLocaleString()}</Text>
|
|
|
</View>
|
|
|
+ {order.payState === 2 && (
|
|
|
+ <View className="order-info-item">
|
|
|
+ <Text className="order-info-label">支付时间</Text>
|
|
|
+ <Text className="order-info-value">{new Date(order.createdAt).toLocaleString()}</Text>
|
|
|
+ </View>
|
|
|
+ )}
|
|
|
</View>
|
|
|
- </Card>
|
|
|
+ </View>
|
|
|
</View>
|
|
|
</ScrollView>
|
|
|
|
|
|
{/* 底部操作栏 */}
|
|
|
- <View className="fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200 px-4 py-3">
|
|
|
- <View className="flex space-x-2 justify-end">
|
|
|
- {order.payState === 0 && (
|
|
|
- <>
|
|
|
- <Button variant="outline" onClick={() => {
|
|
|
- Taro.showModal({
|
|
|
- title: '取消订单',
|
|
|
- content: '确定要取消订单吗?',
|
|
|
- success: (res) => {
|
|
|
- if (res.confirm) {
|
|
|
- // 显示输入取消原因的对话框
|
|
|
- Taro.showModal({
|
|
|
- title: '取消原因',
|
|
|
- content: '',
|
|
|
- editable: true,
|
|
|
- placeholderText: '请输入取消原因...',
|
|
|
- success: (reasonRes) => {
|
|
|
- if (reasonRes.confirm && reasonRes.content) {
|
|
|
- cancelOrderMutation.mutate(reasonRes.content)
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
- }}>
|
|
|
- 取消订单
|
|
|
- </Button>
|
|
|
- <Button onClick={() => {
|
|
|
- Taro.navigateTo({
|
|
|
- url: `/pages/payment/index?orderId=${order.id}&amount=${order.payAmount}`
|
|
|
- })
|
|
|
- }}>
|
|
|
- 立即支付
|
|
|
- </Button>
|
|
|
- </>
|
|
|
- )}
|
|
|
-
|
|
|
- {order.payState === 2 && order.state === 0 && (
|
|
|
- <Button variant="outline" onClick={() => {
|
|
|
- Taro.showModal({
|
|
|
- title: '取消订单',
|
|
|
- content: '确定要取消订单吗?(已支付订单将触发退款流程)',
|
|
|
- success: (res) => {
|
|
|
- if (res.confirm) {
|
|
|
- // 显示输入取消原因的对话框
|
|
|
- Taro.showModal({
|
|
|
- title: '取消原因',
|
|
|
- content: '',
|
|
|
- editable: true,
|
|
|
- placeholderText: '请输入取消原因...',
|
|
|
- success: (reasonRes) => {
|
|
|
- if (reasonRes.confirm && reasonRes.content) {
|
|
|
- cancelOrderMutation.mutate(reasonRes.content)
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
- }}>
|
|
|
- 取消订单
|
|
|
- </Button>
|
|
|
- )}
|
|
|
-
|
|
|
- {order.state === 1 && (
|
|
|
- <Button onClick={() => {
|
|
|
- Taro.showModal({
|
|
|
- title: '确认收货',
|
|
|
- content: '确认已收到商品吗?',
|
|
|
- success: (res) => {
|
|
|
- if (res.confirm) {
|
|
|
- // 调用确认收货API
|
|
|
- Taro.showToast({
|
|
|
- title: '已确认收货',
|
|
|
- icon: 'success'
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
- }}>
|
|
|
- 确认收货
|
|
|
- </Button>
|
|
|
- )}
|
|
|
-
|
|
|
- {order.state === 2 && (
|
|
|
- <Button variant="outline" onClick={() => {
|
|
|
- Taro.navigateTo({
|
|
|
- url: `/pages/order-refund/index?orderId=${order.id}`
|
|
|
- })
|
|
|
- }}>
|
|
|
- 申请退款
|
|
|
- </Button>
|
|
|
- )}
|
|
|
- </View>
|
|
|
+ <View className="order-action-bar">
|
|
|
+ <OrderButtonBar
|
|
|
+ order={order}
|
|
|
+ onViewDetail={() => {}}
|
|
|
+ />
|
|
|
</View>
|
|
|
</View>
|
|
|
)
|