Files
template-10584/src/user/gift/use.tsx
赵忠林 3a42eaf853 feat(gift): 将礼品卡功能重命名为水票并添加新增页面路由
- 将所有"礼品卡"文本替换为"水票",包括页面标题、组件文案、注释等
- 修改首页导航,将充值水票按钮指向我的水票页面
- 调整订水按钮链接直接跳转到商品详情页
- 移除帮助按钮相关代码
- 更新数据转换函数中的面值规格文案
- 修改核销成功提示中的商品类型文案
- 调整空状态提示文案为水票相关内容
- 在应用配置中添加新的水票添加页面路由
- 更新类型定义中的注释说明
2026-01-31 13:39:10 +08:00

291 lines
8.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {useState, useEffect} from "react";
import {useRouter} from '@tarojs/taro'
import {Button, ConfigProvider, Input, TextArea} from '@nutui/nutui-react-taro'
import {ArrowLeft, Location} from '@nutui/icons-react-taro'
import Taro from '@tarojs/taro'
import {View, Text} from '@tarojs/components'
import {ShopGift} from "@/api/shop/shopGift/model";
import {getShopGift, useGift} from "@/api/shop/shopGift";
import GiftCard from "@/components/GiftCard";
const GiftCardUse = () => {
const router = useRouter()
const [gift, setGift] = useState<ShopGift | null>(null)
const [loading, setLoading] = useState(true)
const [submitting, setSubmitting] = useState(false)
const [useLocation, setUseLocation] = useState('')
const [useNote, setUseNote] = useState('')
const [useSuccess, setUseSuccess] = useState(false)
const giftId = router.params.id
useEffect(() => {
if (giftId) {
loadGiftDetail()
}
}, [giftId])
// 加载礼品卡详情
const loadGiftDetail = async () => {
try {
setLoading(true)
const data = await getShopGift(Number(giftId))
setGift(data)
// 如果礼品卡有预设使用地址,自动填入
if (data.useLocation) {
setUseLocation(data.useLocation)
}
} catch (error) {
console.error('获取礼品卡详情失败:', error)
Taro.showToast({
title: '获取礼品卡详情失败',
icon: 'error'
})
} finally {
setLoading(false)
}
}
// 使用礼品卡
const handleUseGift = async () => {
if (!gift) return
// 根据礼品卡类型进行不同的验证
if (gift.type === 10 && !useLocation.trim()) { // 实物礼品卡需要地址
Taro.showToast({
title: '请填写使用地址',
icon: 'none'
})
return
}
setSubmitting(true)
try {
await useGift({
giftId: gift.id!,
useLocation: useLocation.trim(),
useNote: useNote.trim()
})
setUseSuccess(true)
Taro.showToast({
title: '使用成功',
icon: 'success'
})
} catch (error) {
console.error('使用礼品卡失败:', error)
Taro.showToast({
title: '使用失败',
icon: 'error'
})
} finally {
setSubmitting(false)
}
}
// 获取当前位置
const handleGetLocation = () => {
Taro.getLocation({
type: 'gcj02',
success: (res) => {
// 这里可以调用地理编码API将坐标转换为地址
// 暂时使用坐标信息
setUseLocation(`经度:${res.longitude}, 纬度:${res.latitude}`)
Taro.showToast({
title: '位置获取成功',
icon: 'success'
})
},
fail: () => {
Taro.showToast({
title: '位置获取失败',
icon: 'error'
})
}
})
}
// 返回上一页
const handleBack = () => {
Taro.navigateBack()
}
// 查看我的礼品卡
const handleViewMyGifts = () => {
Taro.navigateTo({
url: '/user/gift/index'
})
}
// 转换礼品卡数据
const transformGiftData = (gift: ShopGift) => {
return {
id: gift.id || 0,
name: gift.name || '水票',
description: gift.description,
code: gift.code,
goodsImage: gift.goodsImage,
faceValue: gift.faceValue,
type: gift.type,
expireTime: gift.expireTime,
takeTime: gift.takeTime,
useLocation: gift.useLocation,
contactInfo: gift.contactInfo,
showCode: false,
showUseBtn: false,
showDetailBtn: false,
theme: 'gold' as const
}
}
if (loading) {
return (
<ConfigProvider>
<View className="flex justify-center items-center h-screen">
<Text>...</Text>
</View>
</ConfigProvider>
)
}
if (!gift) {
return (
<ConfigProvider>
<View className="flex flex-col justify-center items-center h-screen">
<Text className="text-gray-500 mb-4"></Text>
<Button onClick={handleBack}></Button>
</View>
</ConfigProvider>
)
}
return (
<ConfigProvider>
{/* 自定义导航栏 */}
<View className="flex items-center justify-between p-4 bg-white border-b border-gray-100">
<View className="flex items-center" onClick={handleBack}>
<ArrowLeft size="20" />
<Text className="ml-2 text-lg">使</Text>
</View>
</View>
{!useSuccess ? (
<>
{/* 礼品卡信息 */}
<View className="mx-4 mt-4">
<GiftCard {...transformGiftData(gift)} />
</View>
{/* 使用表单 */}
<View className="bg-white mx-4 mt-4 p-4 rounded-xl">
<Text className="font-semibold mb-4 text-gray-800">使</Text>
{/* 使用地址(实物礼品卡必填) */}
{gift.type === 10 && (
<View className="mb-4">
<Text className="text-gray-700 mb-2">使 *</Text>
<View className="flex gap-2">
<Input
placeholder="请输入使用地址"
value={useLocation}
onChange={setUseLocation}
className="flex-1 border border-gray-200 rounded-lg"
/>
<Button
size="small"
fill="outline"
icon={<Location />}
onClick={handleGetLocation}
>
</Button>
</View>
</View>
)}
{/* 虚拟礼品卡和服务礼品卡的地址选填 */}
{gift.type !== 10 && (
<View className="mb-4">
<Text className="text-gray-700 mb-2">使</Text>
<Input
placeholder="请输入使用地址"
value={useLocation}
onChange={setUseLocation}
className="border border-gray-200 rounded-lg"
/>
</View>
)}
{/* 使用备注 */}
<View className="mb-4">
<Text className="text-gray-700 mb-2">使</Text>
<TextArea
placeholder="请输入使用备注"
value={useNote}
onChange={setUseNote}
rows={3}
className="border border-gray-200 rounded-lg"
/>
</View>
{/* 使用说明 */}
<View className="bg-yellow-50 p-3 rounded-lg border border-yellow-200 mb-4">
<Text className="text-yellow-800 text-sm">
{gift.type === 10 && '💡 实物礼品卡使用后请到指定地址领取商品'}
{gift.type === 20 && '💡 虚拟礼品卡使用后将自动发放到您的账户'}
{gift.type === 30 && '💡 服务礼品卡使用后请联系客服预约服务时间'}
</Text>
</View>
<Button
type="primary"
size="large"
block
loading={submitting}
onClick={handleUseGift}
>
使
</Button>
</View>
</>
) : (
/* 使用成功页面 */
<View className="flex flex-col items-center justify-center px-4" style={{height: '600px'}}>
<View className="text-center">
<View className="w-20 h-20 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4">
{/*<Voucher size="40" className="text-green-600" />*/}
</View>
<Text className="text-2xl font-bold text-gray-900 mb-2">使</Text>
<Text className="text-gray-600 mb-6">
{gift.type === 10 && '请到指定地址领取您的商品'}
{gift.type === 20 && '虚拟商品已发放到您的账户'}
{gift.type === 30 && '请联系客服预约服务时间'}
</Text>
{gift.contactInfo && (
<View className="bg-blue-50 p-4 rounded-lg mb-6 border border-blue-200">
<Text className="text-blue-800 font-semibold mb-1"></Text>
<Text className="text-blue-700">{gift.contactInfo}</Text>
</View>
)}
<View className="flex flex-col gap-3 w-full max-w-xs">
<Button
type="primary"
size="large"
block
onClick={handleViewMyGifts}
>
</Button>
</View>
</View>
</View>
)}
</ConfigProvider>
);
};
export default GiftCardUse;