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 className={'item flex justify-center flex-col items-center'}
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>
</div>
{/*<div className={'item flex justify-center flex-col items-center'}>*/}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -65,7 +65,7 @@ const UserCard = forwardRef<any, any>((_, ref) => {
setUserInfo(data)
setIsLogin(true);
Taro.setStorageSync('UserId', data.userId)
// 登录态已就绪后刷新卡片统计(余额/积分/券/礼品卡
// 登录态已就绪后刷新卡片统计(余额/积分/券/水票
refresh().then()
// 获取openId
@@ -164,7 +164,7 @@ const UserCard = forwardRef<any, any>((_, ref) => {
Taro.setStorageSync('UserId', res.data.data.user.userId)
setUserInfo(res.data.data.user)
setIsLogin(true)
// 登录态已就绪后刷新卡片统计(余额/积分/券/礼品卡
// 登录态已就绪后刷新卡片统计(余额/积分/券/水票
refresh().then()
}
})
@@ -228,7 +228,7 @@ const UserCard = forwardRef<any, any>((_, ref) => {
// 核销成功,可以显示更多信息或跳转到详情页
Taro.showModal({
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 className={'item flex justify-center flex-col items-center'}
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>
</View>
</View>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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