| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- import { View, Text } from '@tarojs/components'
- import Taro from '@tarojs/taro'
- import { useMutation, useQueryClient } from '@tanstack/react-query'
- import { InferResponseType } from 'hono'
- import { orderClient } from '@/api'
- import { useState } from 'react'
- import CancelReasonDialog from '@/components/common/CancelReasonDialog'
- type OrderResponse = InferResponseType<typeof orderClient.$get, 200>
- type Order = OrderResponse['data'][0]
- interface OrderButtonBarProps {
- order: Order
- onViewDetail: (order: Order) => void
- onCancelOrder?: () => void
- }
- interface ActionButton {
- text: string
- type: 'primary' | 'outline'
- onClick: () => void
- }
- export default function OrderButtonBar({ order, onViewDetail, onCancelOrder }: OrderButtonBarProps) {
- const queryClient = useQueryClient()
- const [showCancelDialog, setShowCancelDialog] = useState(false)
- // 取消订单mutation
- const cancelOrderMutation = useMutation({
- mutationFn: async ({ orderId, reason }: { orderId: number; reason: string }) => {
- const response = await orderClient.cancelOrder.$post({
- json: {
- orderId,
- reason
- }
- })
- if (response.status !== 200) {
- throw new Error('取消订单失败')
- }
- return response.json()
- },
- onSuccess: (data) => {
- // 取消成功后刷新订单列表数据
- queryClient.invalidateQueries({ queryKey: ['orders'] })
- queryClient.invalidateQueries({ queryKey: ['order', order.id] })
- // 显示取消成功信息
- Taro.showToast({
- title: '订单取消成功',
- icon: 'success',
- duration: 2000
- })
- // 如果订单已支付,显示退款流程信息
- if (order.payState === 2) {
- setTimeout(() => {
- Taro.showModal({
- title: '退款处理中',
- content: '您的退款申请已提交,退款金额将在1-3个工作日内原路退回。',
- showCancel: false,
- confirmText: '知道了'
- })
- }, 1500)
- }
- },
- onError: (error) => {
- // 根据错误消息类型显示不同的用户友好提示
- let errorMessage = '取消失败,请稍后重试'
- if (error.message.includes('订单不存在')) {
- errorMessage = '订单不存在或已被删除'
- } else if (error.message.includes('订单状态不允许取消')) {
- errorMessage = '当前订单状态不允许取消'
- } else if (error.message.includes('网络')) {
- errorMessage = '网络连接失败,请检查网络后重试'
- }
- Taro.showToast({
- title: errorMessage,
- icon: 'error',
- duration: 3000
- })
- }
- })
- // 处理取消原因确认
- const handleCancelReasonConfirm = (reason: string) => {
- // 显示确认对话框
- Taro.showModal({
- title: '确认取消',
- content: `确定要取消订单吗?\n取消原因:${reason}`,
- success: (confirmRes) => {
- if (confirmRes.confirm) {
- // 调用取消订单API
- cancelOrderMutation.mutate({
- orderId: order.id,
- reason
- })
- }
- }
- })
- }
- // 取消订单
- const handleCancelOrder = () => {
- // 检查网络连接
- Taro.getNetworkType({
- success: (res) => {
- if (res.networkType === 'none') {
- Taro.showToast({
- title: '网络连接失败,请检查网络后重试',
- icon: 'error',
- duration: 3000
- })
- return
- }
- if (onCancelOrder) {
- // 使用外部提供的取消订单处理函数
- onCancelOrder()
- } else {
- // 使用组件内部的取消订单处理
- setShowCancelDialog(true)
- }
- },
- fail: () => {
- Taro.showToast({
- title: '网络状态检查失败',
- icon: 'error',
- duration: 3000
- })
- }
- })
- }
- // 去支付
- const handlePayOrder = () => {
- Taro.navigateTo({
- url: `/pages/payment/index?orderId=${order.id}&amount=${order.payAmount}`
- })
- }
- // 确认收货
- const handleConfirmReceipt = () => {
- Taro.showModal({
- title: '确认收货',
- content: '确认已收到商品吗?',
- success: async (res) => {
- if (res.confirm) {
- try {
- // 这里调用确认收货的API
- Taro.showToast({
- title: '已确认收货',
- icon: 'success'
- })
- } catch (error) {
- Taro.showToast({
- title: '确认失败',
- icon: 'error'
- })
- }
- }
- }
- })
- }
- // 申请退款
- const handleApplyRefund = () => {
- Taro.showModal({
- title: '申请退款',
- content: '确定要申请退款吗?',
- success: async (res) => {
- if (res.confirm) {
- try {
- // 这里调用申请退款的API
- Taro.showToast({
- title: '退款申请已提交',
- icon: 'success'
- })
- } catch (error) {
- Taro.showToast({
- title: '申请失败',
- icon: 'error'
- })
- }
- }
- }
- })
- }
- // 查看物流
- const handleViewLogistics = () => {
- Taro.showToast({
- title: '物流信息开发中',
- icon: 'none'
- })
- }
- // 根据订单状态显示不同的操作按钮
- const getActionButtons = (order: Order): ActionButton[] => {
- const buttons: ActionButton[] = []
- // 查看详情按钮 - 所有状态都显示
- buttons.push({
- text: '查看详情',
- type: 'outline',
- onClick: () => onViewDetail(order)
- })
- // 根据支付状态和订单状态显示不同的操作按钮
- if (order.payState === 0) {
- // 未支付
- buttons.push({
- text: '去支付',
- type: 'primary',
- onClick: handlePayOrder
- })
- buttons.push({
- text: '取消订单',
- type: 'outline',
- onClick: handleCancelOrder
- })
- } else if (order.payState === 2) {
- // 已支付
- if (order.state === 0) {
- // 待发货
- buttons.push({
- text: '申请退款',
- type: 'outline',
- onClick: handleApplyRefund
- })
- } else if (order.state === 1) {
- // 已发货
- buttons.push({
- text: '确认收货',
- type: 'primary',
- onClick: handleConfirmReceipt
- })
- buttons.push({
- text: '查看物流',
- type: 'outline',
- onClick: handleViewLogistics
- })
- } else if (order.state === 2) {
- // 已完成
- buttons.push({
- text: '申请售后',
- type: 'outline',
- onClick: handleApplyRefund
- })
- }
- }
- return buttons
- }
- const actionButtons = getActionButtons(order)
- return (
- <>
- <View className="flex justify-end space-x-2">
- {actionButtons.map((button, index) => (
- <View
- key={index}
- className={`px-4 py-2 rounded-full text-sm font-medium border ${
- button.type === 'primary'
- ? 'bg-primary text-white border-primary'
- : 'bg-white text-gray-600 border-gray-300'
- } ${cancelOrderMutation.isPending && button.text === '取消订单' ? 'opacity-50' : ''}`}
- onClick={cancelOrderMutation.isPending && button.text === '取消订单' ? undefined : button.onClick}
- data-testid={button.text === '取消订单' ? 'cancel-order-button' : undefined}
- >
- <Text>
- {cancelOrderMutation.isPending && button.text === '取消订单' ? '取消中...' : button.text}
- </Text>
- </View>
- ))}
- </View>
- <CancelReasonDialog
- open={showCancelDialog}
- onOpenChange={setShowCancelDialog}
- onConfirm={handleCancelReasonConfirm}
- loading={cancelOrderMutation.isPending}
- />
- </>
- )
- }
|