feat(gift): 将礼品卡功能重命名为水票并添加新增页面路由

- 将所有"礼品卡"文本替换为"水票",包括页面标题、组件文案、注释等
- 修改首页导航,将充值水票按钮指向我的水票页面
- 调整订水按钮链接直接跳转到商品详情页
- 移除帮助按钮相关代码
- 更新数据转换函数中的面值规格文案
- 修改核销成功提示中的商品类型文案
- 调整空状态提示文案为水票相关内容
- 在应用配置中添加新的水票添加页面路由
- 更新类型定义中的注释说明
This commit is contained in:
2026-01-31 13:39:10 +08:00
parent f5c6d52b78
commit 3a42eaf853
17 changed files with 77 additions and 76 deletions

View File

@@ -237,7 +237,7 @@ function UserCard() {
</div> </div>
<div className={'item flex justify-center flex-col items-center'} <div className={'item flex justify-center flex-col items-center'}
onClick={() => navTo('/user/gift/index', true)}> onClick={() => navTo('/user/gift/index', true)}>
<span className={'text-sm text-gray-500'}></span> <span className={'text-sm text-gray-500'}></span>
<span className={'text-xl'}>{giftCount}</span> <span className={'text-xl'}>{giftCount}</span>
</div> </div>
{/*<div className={'item flex justify-center flex-col items-center'}>*/} {/*<div className={'item flex justify-center flex-col items-center'}>*/}

View File

@@ -1,7 +1,7 @@
import type { PageParam } from '@/api'; import type { PageParam } from '@/api';
/** /**
* 礼品卡 * 水票
*/ */
export interface ShopGift { export interface ShopGift {
// 礼品卡ID // 礼品卡ID

View File

@@ -43,7 +43,7 @@ export interface UserOrderStats {
total: number total: number
} }
// 用户卡片统计(个人中心头部:余额/积分/优惠券/礼品卡 // 用户卡片统计(个人中心头部:余额/积分/优惠券/水票
export interface UserCardStats { export interface UserCardStats {
balance: string balance: string
points: number points: number

View File

@@ -56,6 +56,7 @@ export default {
"gift/index", "gift/index",
"gift/redeem", "gift/redeem",
"gift/detail", "gift/detail",
"gift/add",
"store/verification", "store/verification",
"theme/index", "theme/index",
"poster/poster", "poster/poster",

View File

@@ -24,7 +24,7 @@ export interface GiftCardProps {
faceValue?: string faceValue?: string
/** 商品原价 */ /** 商品原价 */
originalPrice?: string originalPrice?: string
/** 礼品卡类型10-实物礼品 20-虚拟礼品卡 30-服务礼品卡 */ /** 礼品卡类型10-礼品 20-虚拟礼品卡 30-服务礼品卡 */
type?: number type?: number
/** 状态0-未使用 1-已使用 2-失效 */ /** 状态0-未使用 1-已使用 2-失效 */
status?: number status?: number
@@ -112,10 +112,10 @@ const GiftCard: React.FC<GiftCardProps> = ({
// 获取礼品卡类型文本 // 获取礼品卡类型文本
const getTypeText = () => { const getTypeText = () => {
switch (type) { switch (type) {
case 10: return '实物礼品' case 10: return '礼品'
case 20: return '虚拟礼品卡' case 20: return '虚拟礼品卡'
case 30: return '服务礼品卡' case 30: return '服务礼品卡'
default: return '礼品卡' default: return '水票'
} }
} }

View File

@@ -51,7 +51,7 @@ const GiftCardGuide: React.FC<GiftCardGuideProps> = ({
title: '礼品卡类型说明', title: '礼品卡类型说明',
icon: <Gift size="24" className="text-purple-500" />, icon: <Gift size="24" className="text-purple-500" />,
content: [ content: [
'🎁 实物礼品:需到指定地址领取商品', '🎁 礼品:需到指定地址领取商品',
'💻 虚拟礼品卡:自动发放到账户余额', '💻 虚拟礼品卡:自动发放到账户余额',
'🛎️ 服务礼品卡:联系客服预约服务', '🛎️ 服务礼品卡:联系客服预约服务',
'⏰ 注意查看有效期,过期无法使用' '⏰ 注意查看有效期,过期无法使用'

View File

@@ -28,10 +28,10 @@ const GiftCardShare: React.FC<GiftCardShareProps> = ({
// 获取礼品卡类型文本 // 获取礼品卡类型文本
const getTypeText = () => { const getTypeText = () => {
switch (giftCard.type) { switch (giftCard.type) {
case 10: return '实物礼品' case 10: return '礼品'
case 20: return '虚拟礼品卡' case 20: return '虚拟礼品卡'
case 30: return '服务礼品卡' case 30: return '服务礼品卡'
default: return '礼品卡' default: return '水票'
} }
} }

View File

@@ -161,15 +161,15 @@ function Home() {
() => [ () => [
{ {
key: 'ticket', key: 'ticket',
title: '充值水票', title: '我的水票',
icon: <Ticket size={30} />, icon: <Ticket size={30} />,
onClick: () => Taro.navigateTo({ url: '/user/wallet/wallet' }), onClick: () => Taro.navigateTo({ url: '/user/gift/index' }),
}, },
{ {
key: 'order', key: 'order',
title: '立即订水', title: '立即订水',
icon: <Cart size={30} />, icon: <Cart size={30} />,
onClick: () => Taro.switchTab({ url: '/pages/category/index' }), onClick: () => Taro.navigateTo({ url: '/shop/goodsDetail/index?id=10072' }),
}, },
{ {
key: 'invite', key: 'invite',

View File

@@ -65,7 +65,7 @@ const UserCard = forwardRef<any, any>((_, ref) => {
setUserInfo(data) setUserInfo(data)
setIsLogin(true); setIsLogin(true);
Taro.setStorageSync('UserId', data.userId) Taro.setStorageSync('UserId', data.userId)
// 登录态已就绪后刷新卡片统计(余额/积分/券/礼品卡 // 登录态已就绪后刷新卡片统计(余额/积分/券/水票
refresh().then() refresh().then()
// 获取openId // 获取openId
@@ -164,7 +164,7 @@ const UserCard = forwardRef<any, any>((_, ref) => {
Taro.setStorageSync('UserId', res.data.data.user.userId) Taro.setStorageSync('UserId', res.data.data.user.userId)
setUserInfo(res.data.data.user) setUserInfo(res.data.data.user)
setIsLogin(true) setIsLogin(true)
// 登录态已就绪后刷新卡片统计(余额/积分/券/礼品卡 // 登录态已就绪后刷新卡片统计(余额/积分/券/水票
refresh().then() refresh().then()
} }
}) })
@@ -228,7 +228,7 @@ const UserCard = forwardRef<any, any>((_, ref) => {
// 核销成功,可以显示更多信息或跳转到详情页 // 核销成功,可以显示更多信息或跳转到详情页
Taro.showModal({ Taro.showModal({
title: '核销成功', title: '核销成功',
content: `已成功核销的品类:${result.data.goodsName || '礼品卡'},面值¥${result.data.faceValue}` content: `已成功核销的品类:${result.data.goodsName || '水票'},面值¥${result.data.faceValue}`
}); });
} }
}} }}
@@ -256,7 +256,7 @@ const UserCard = forwardRef<any, any>((_, ref) => {
</View> </View>
<View className={'item flex justify-center flex-col items-center'} <View className={'item flex justify-center flex-col items-center'}
onClick={() => navTo('/user/gift/index', true)}> onClick={() => navTo('/user/gift/index', true)}>
<Text className={'text-xs text-gray-200'} style={themeStyles.textColor}></Text> <Text className={'text-xs text-gray-200'} style={themeStyles.textColor}></Text>
<Text className={'text-xl text-white'} style={themeStyles.textColor}>{data?.giftCards || 0}</Text> <Text className={'text-xl text-white'} style={themeStyles.textColor}>{data?.giftCards || 0}</Text>
</View> </View>
</View> </View>

View File

@@ -193,7 +193,7 @@ const UnifiedQRPage: React.FC = () => {
{result.type === ScanType.VERIFICATION && result.data && ( {result.type === ScanType.VERIFICATION && result.data && (
<View className="bg-green-50 rounded-lg p-3 mb-4"> <View className="bg-green-50 rounded-lg p-3 mb-4">
<Text className="text-sm text-green-800 block"> <Text className="text-sm text-green-800 block">
{result.data.goodsName || '未知商品'} {result.data.goodsName || '未知商品'}
</Text> </Text>
<Text className="text-sm text-green-800 block"> <Text className="text-sm text-green-800 block">
¥{result.data.faceValue} ¥{result.data.faceValue}

View File

@@ -4,7 +4,7 @@
/** 礼品卡类型枚举 */ /** 礼品卡类型枚举 */
export enum GiftCardType { export enum GiftCardType {
/** 实物礼品 */ /** 礼品 */
PHYSICAL = 10, PHYSICAL = 10,
/** 虚拟礼品卡 */ /** 虚拟礼品卡 */
VIRTUAL = 20, VIRTUAL = 20,

View File

@@ -43,10 +43,10 @@ const GiftCardDetail = () => {
// 获取礼品卡类型文本 // 获取礼品卡类型文本
const getGiftTypeText = (type?: number) => { const getGiftTypeText = (type?: number) => {
switch (type) { switch (type) {
case 10: return '实物礼品' case 10: return '礼品'
case 20: return '虚拟礼品卡' case 20: return '虚拟礼品卡'
case 30: return '服务礼品卡' case 30: return '服务礼品卡'
default: return '礼品卡' default: return '水票'
} }
} }

View File

@@ -1,5 +1,5 @@
export default definePageConfig({ export default definePageConfig({
navigationBarTitleText: '我的礼品卡', navigationBarTitleText: '我的水票',
navigationBarTextStyle: 'black', navigationBarTextStyle: 'black',
navigationBarBackgroundColor: '#ffffff' navigationBarBackgroundColor: '#ffffff'
}) })

View File

@@ -1,7 +1,7 @@
import {useState} from "react"; import {useState} from "react";
import Taro, {useDidShow} from '@tarojs/taro' import Taro, {useDidShow} from '@tarojs/taro'
import {Button, Empty, ConfigProvider,SearchBar, InfiniteLoading, Loading, PullToRefresh, Tabs, TabPane} from '@nutui/nutui-react-taro' import {Button, Empty, ConfigProvider,SearchBar, InfiniteLoading, Loading, PullToRefresh, Tabs, TabPane} from '@nutui/nutui-react-taro'
import {Gift, Retweet, Board, QrCode} from '@nutui/icons-react-taro' import {Gift, Retweet, QrCode} from '@nutui/icons-react-taro'
import {View} from '@tarojs/components' import {View} from '@tarojs/components'
import {ShopGift} from "@/api/shop/shopGift/model"; import {ShopGift} from "@/api/shop/shopGift/model";
import {getUserGifts} from "@/api/shop/shopGift"; import {getUserGifts} from "@/api/shop/shopGift";
@@ -24,7 +24,7 @@ const GiftCardManage = () => {
// sortOrder: 'desc' as 'asc' | 'desc' // sortOrder: 'desc' as 'asc' | 'desc'
// }) // })
// 获取礼品卡状态过滤条件 // 获取水票状态过滤条件
const getStatusFilter = () => { const getStatusFilter = () => {
switch (String(activeTab)) { switch (String(activeTab)) {
case '0': // 未使用 case '0': // 未使用
@@ -52,7 +52,7 @@ const GiftCardManage = () => {
} }
} }
// 根据状态过滤条件加载礼品卡 // 根据状态过滤条件加载水票
const loadGiftsByStatus = async (statusFilter: any) => { const loadGiftsByStatus = async (statusFilter: any) => {
setLoading(true) setLoading(true)
try { try {
@@ -72,9 +72,9 @@ const GiftCardManage = () => {
setHasMore(false) setHasMore(false)
} }
} catch (error) { } catch (error) {
console.error('获取礼品卡失败:', error) console.error('获取水票失败:', error)
Taro.showToast({ Taro.showToast({
title: '获取礼品卡失败', title: '获取水票失败',
icon: 'error' icon: 'error'
}) })
} finally { } finally {
@@ -125,9 +125,9 @@ const GiftCardManage = () => {
// setTotal(0) // setTotal(0)
} }
} catch (error) { } catch (error) {
console.error('获取礼品卡失败:', error) console.error('获取水票失败:', error)
Taro.showToast({ Taro.showToast({
title: '获取礼品卡失败', title: '获取水票失败',
icon: 'error' icon: 'error'
}); });
} finally { } finally {
@@ -162,11 +162,11 @@ const GiftCardManage = () => {
loadGiftsByStatus(statusFilter) loadGiftsByStatus(statusFilter)
} }
// 转换礼品卡数据为GiftCard组件所需格式 // 转换水票数据为GiftCard组件所需格式
const transformGiftData = (gift: ShopGift): GiftCardProps => { const transformGiftData = (gift: ShopGift): GiftCardProps => {
return { return {
id: gift.id || 0, id: gift.id || 0,
name: gift.name || '礼品卡', // 礼品卡名称 name: gift.name || '水票', // 水票名称
goodsName: gift.goodsName, // 商品名称(新增字段) goodsName: gift.goodsName, // 商品名称(新增字段)
description: gift.description || gift.instructions, // 使用说明作为描述 description: gift.description || gift.instructions, // 使用说明作为描述
code: gift.code, code: gift.code,
@@ -180,23 +180,23 @@ const GiftCardManage = () => {
contactInfo: gift.contactInfo, contactInfo: gift.contactInfo,
// 添加商品信息 // 添加商品信息
goodsInfo: { goodsInfo: {
// 如果有商品名称或商品ID说明是关联商品的礼品卡 // 如果有商品名称或商品ID说明是关联商品的水票
...((gift.goodsName || gift.goodsId) && { ...((gift.goodsName || gift.goodsId) && {
specification: `礼品卡面值:¥${gift.faceValue}`, specification: `水票面值:¥${gift.faceValue}`,
category: getTypeText(gift.type), category: getTypeText(gift.type),
tags: [ tags: [
getTypeText(gift.type), getTypeText(gift.type),
gift.status === 0 ? '未使用' : gift.status === 1 ? '已使用' : '失效', gift.status === 0 ? '未使用' : gift.status === 1 ? '已使用' : '失效',
...(gift.goodsName ? ['商品礼品卡'] : []) ...(gift.goodsName ? ['商品水票'] : [])
].filter(Boolean), ].filter(Boolean),
instructions: gift.instructions ? [gift.instructions] : [ instructions: gift.instructions ? [gift.instructions] : [
'请在有效期内使用', '请在有效期内使用',
'出示兑换码即可使用', '出示兑换码即可使用',
'不可兑换现金', '不可兑换现金',
...(gift.goodsName ? ['此礼品卡关联具体商品'] : []) ...(gift.goodsName ? ['此水票关联具体商品'] : [])
], ],
notices: [ notices: [
'礼品卡一经使用不可退换', '水票一经使用不可退换',
'请妥善保管兑换码', '请妥善保管兑换码',
'如有疑问请联系客服', '如有疑问请联系客服',
...(gift.goodsName ? ['商品以实际为准'] : []) ...(gift.goodsName ? ['商品以实际为准'] : [])
@@ -213,34 +213,34 @@ const GiftCardManage = () => {
} }
} }
// 获取礼品卡类型文本 // 获取水票类型文本
const getTypeText = (type?: number): string => { const getTypeText = (type?: number): string => {
switch (type) { switch (type) {
case 10: return '实物礼品卡' case 10: return '实物水票'
case 20: return '虚拟礼品卡' case 20: return '虚拟水票'
case 30: return '服务礼品卡' case 30: return '服务水票'
default: return '礼品卡' default: return '水票'
} }
} }
// 根据礼品卡类型获取主题色 // 根据水票类型获取主题色
const getThemeByType = (type?: number): 'gold' | 'silver' | 'bronze' | 'blue' | 'green' | 'purple' => { const getThemeByType = (type?: number): 'gold' | 'silver' | 'bronze' | 'blue' | 'green' | 'purple' => {
switch (type) { switch (type) {
case 10: return 'gold' // 实物礼品卡 - 金色 case 10: return 'gold' // 实物水票 - 金色
case 20: return 'blue' // 虚拟礼品卡 - 蓝色 case 20: return 'blue' // 虚拟水票 - 蓝色
case 30: return 'green' // 服务礼品卡 - 绿色 case 30: return 'green' // 服务水票 - 绿色
default: return 'purple' // 默认使用紫色主题,更美观 default: return 'purple' // 默认使用紫色主题,更美观
} }
} }
// 使用礼品卡 // 使用水票
const handleUseGift = (gift: ShopGift) => { const handleUseGift = (gift: ShopGift) => {
Taro.showModal({ Taro.showModal({
title: '使用礼品卡', title: '使用水票',
content: `确定要使用"${gift.name}"吗?`, content: `确定要使用"${gift.name}"吗?`,
success: (res) => { success: (res) => {
if (res.confirm) { if (res.confirm) {
// 跳转到礼品卡使用页面 // 跳转到水票使用页面
Taro.navigateTo({ Taro.navigateTo({
url: `/user/gift/use?id=${gift.id}` url: `/user/gift/use?id=${gift.id}`
}) })
@@ -249,35 +249,35 @@ const GiftCardManage = () => {
}) })
} }
// 礼品卡点击事件 // 水票点击事件
const handleGiftClick = (gift: GiftCardProps, index: number) => { const handleGiftClick = (gift: GiftCardProps, index: number) => {
console.log(gift.code) console.log(gift.code)
const originalGift = list[index] const originalGift = list[index]
if (originalGift) { if (originalGift) {
// 显示礼品卡详情 // 显示水票详情
handleGiftDetail(originalGift) handleGiftDetail(originalGift)
} }
} }
// 显示礼品卡详情 // 显示水票详情
const handleGiftDetail = (gift: ShopGift) => { const handleGiftDetail = (gift: ShopGift) => {
// 跳转到礼品卡详情页 // 跳转到水票详情页
Taro.navigateTo({ Taro.navigateTo({
url: `/user/gift/detail?id=${gift.id}` url: `/user/gift/detail?id=${gift.id}`
}) })
} }
// 加载礼品卡统计数据 // 加载水票统计数据
// const loadGiftStats = async () => { // const loadGiftStats = async () => {
// try { // try {
// // 并行获取各状态的礼品卡数量 // // 并行获取各状态的水票数量
// const [availableRes, usedRes, expiredRes] = await Promise.all([ // const [availableRes, usedRes, expiredRes] = await Promise.all([
// getUserGifts({ page: 1, limit: 1, useStatus: 0 }), // getUserGifts({ page: 1, limit: 1, useStatus: 0 }),
// getUserGifts({ page: 1, limit: 1, useStatus: 1 }), // getUserGifts({ page: 1, limit: 1, useStatus: 1 }),
// getUserGifts({ page: 1, limit: 1, useStatus: 2 }) // getUserGifts({ page: 1, limit: 1, useStatus: 2 })
// ]) // ])
// //
// // 计算总价值(仅可用礼品卡 // // 计算总价值(仅可用水票
// const availableGifts = await getUserGifts({ page: 1, limit: 100, useStatus: 0 }) // const availableGifts = await getUserGifts({ page: 1, limit: 100, useStatus: 0 })
// const totalValue = availableGifts?.list?.reduce((sum, gift) => { // const totalValue = availableGifts?.list?.reduce((sum, gift) => {
// return sum + parseFloat(gift.faceValue || '0') // return sum + parseFloat(gift.faceValue || '0')
@@ -290,7 +290,7 @@ const GiftCardManage = () => {
// totalValue // totalValue
// }) // })
// } catch (error) { // } catch (error) {
// console.error('获取礼品卡统计失败:', error) // console.error('获取水票统计失败:', error)
// } // }
// } // }
@@ -300,21 +300,21 @@ const GiftCardManage = () => {
// available: '0', // available: '0',
// used: '1', // used: '1',
// expired: '2', // expired: '2',
// total: '0' // 总价值点击跳转到可用礼品卡 // total: '0' // 总价值点击跳转到可用水票
// } // }
// if (tabMap[type]) { // if (tabMap[type]) {
// handleTabChange(tabMap[type]) // handleTabChange(tabMap[type])
// } // }
// } // }
// 兑换礼品卡 // 兑换水票
const handleRedeemGift = () => { const handleRedeemGift = () => {
Taro.navigateTo({ Taro.navigateTo({
url: '/user/gift/redeem' url: '/user/gift/redeem'
}) })
} }
// 扫码兑换礼品卡 // 扫码兑换水票
const handleScanRedeem = () => { const handleScanRedeem = () => {
Taro.scanCode({ Taro.scanCode({
success: (res) => { success: (res) => {
@@ -377,14 +377,14 @@ const GiftCardManage = () => {
> >
</Button> </Button>
<Button {/*<Button*/}
size="small" {/* size="small"*/}
fill="outline" {/* fill="outline"*/}
icon={<Board />} {/* icon={<Board />}*/}
onClick={() => setShowGuide(true)} {/* onClick={() => setShowGuide(true)}*/}
> {/*>*/}
{/* 帮助*/}
</Button> {/*</Button>*/}
</View> </View>
</View> </View>
@@ -400,7 +400,7 @@ const GiftCardManage = () => {
</Tabs> </Tabs>
</View> </View>
{/* 礼品卡列表 */} {/* 水票列表 */}
<PullToRefresh <PullToRefresh
onRefresh={handleRefresh} onRefresh={handleRefresh}
headHeight={60} headHeight={60}
@@ -410,9 +410,9 @@ const GiftCardManage = () => {
<View className="flex flex-col justify-center items-center" style={{height: '500px'}}> <View className="flex flex-col justify-center items-center" style={{height: '500px'}}>
<Empty <Empty
description={ description={
activeTab === '0' ? "暂无未使用礼品卡" : activeTab === '0' ? "暂无未使用水票" :
activeTab === '1' ? "暂无已使用礼品卡" : activeTab === '1' ? "暂无已使用水票" :
"暂无失效礼品卡" "暂无失效水票"
} }
style={{backgroundColor: 'transparent'}} style={{backgroundColor: 'transparent'}}
/> />
@@ -450,14 +450,14 @@ const GiftCardManage = () => {
<View className="text-gray-400 mb-4"> <View className="text-gray-400 mb-4">
<Gift size="48" /> <Gift size="48" />
</View> </View>
<View className="text-gray-500 mb-2">使</View> <View className="text-gray-500 mb-2">使</View>
<View className="flex gap-2 justify-center"> <View className="flex gap-2 justify-center">
<Button <Button
size="small" size="small"
type="primary" type="primary"
onClick={handleRedeemGift} onClick={handleRedeemGift}
> >
</Button> </Button>
<Button <Button
size="small" size="small"

View File

@@ -130,7 +130,7 @@ const GiftCardRedeem = () => {
const transformGiftData = (gift: ShopGift) => { const transformGiftData = (gift: ShopGift) => {
return { return {
id: gift.id || 0, id: gift.id || 0,
name: gift.name || '礼品卡', name: gift.name || '水票',
description: gift.description, description: gift.description,
code: gift.code, code: gift.code,
goodsImage: gift.goodsImage, goodsImage: gift.goodsImage,

View File

@@ -121,7 +121,7 @@ const GiftCardUse = () => {
const transformGiftData = (gift: ShopGift) => { const transformGiftData = (gift: ShopGift) => {
return { return {
id: gift.id || 0, id: gift.id || 0,
name: gift.name || '礼品卡', name: gift.name || '水票',
description: gift.description, description: gift.description,
code: gift.code, code: gift.code,
goodsImage: gift.goodsImage, goodsImage: gift.goodsImage,

View File

@@ -161,13 +161,13 @@ const StoreVerification: React.FC = () => {
const getTypeText = (type: number) => { const getTypeText = (type: number) => {
switch (type) { switch (type) {
case 10: case 10:
return '实物礼品' return '礼品'
case 20: case 20:
return '虚拟礼品卡' return '虚拟礼品卡'
case 30: case 30:
return '服务礼品卡' return '服务礼品卡'
default: default:
return '礼品卡' return '水票'
} }
} }