forked from gxwebsoft/mp-10550
feat(coupon): 添加优惠券领取中心功能
- 新增优惠券领取中心页面,包含热门优惠券轮播、优惠券列表、筛选功能等 - 实现优惠券数据加载、搜索、下拉刷新、加载更多等功能 - 添加优惠券领取逻辑,支持用户领取优惠券 - 优化邀请小程序码生成和分享功能 -调整首页和用户订单组件的样式
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
export const ENV_CONFIG = {
|
export const ENV_CONFIG = {
|
||||||
// 开发环境
|
// 开发环境
|
||||||
development: {
|
development: {
|
||||||
API_BASE_URL: 'http://127.0.0.1:9200/api',
|
API_BASE_URL: 'https://cms-api.websoft.top/api',
|
||||||
APP_NAME: '开发环境',
|
APP_NAME: '开发环境',
|
||||||
DEBUG: 'true',
|
DEBUG: 'true',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -96,10 +96,10 @@ export interface InviteRecordParam {
|
|||||||
* 生成小程序码
|
* 生成小程序码
|
||||||
*/
|
*/
|
||||||
export async function generateMiniProgramCode(data: MiniProgramCodeParam) {
|
export async function generateMiniProgramCode(data: MiniProgramCodeParam) {
|
||||||
const res = await request.post<ApiResult<string>>(
|
const res = await request.get<ApiResult<string>>(
|
||||||
SERVER_API_URL + '/invite/generate-miniprogram-code',
|
'/wx-login/getOrderQRCodeUnlimited/' + data.scene
|
||||||
data
|
|
||||||
);
|
);
|
||||||
|
console.log(res,'res....')
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
@@ -109,15 +109,15 @@ export async function generateMiniProgramCode(data: MiniProgramCodeParam) {
|
|||||||
/**
|
/**
|
||||||
* 生成邀请小程序码
|
* 生成邀请小程序码
|
||||||
*/
|
*/
|
||||||
export async function generateInviteCode(inviterId: number, source: string = 'qrcode') {
|
export async function generateInviteCode(inviterId: number) {
|
||||||
const scene = `inviter=${inviterId}&source=${source}&t=${Date.now()}`;
|
const scene = `uid_${inviterId}`;
|
||||||
|
|
||||||
return generateMiniProgramCode({
|
return generateMiniProgramCode({
|
||||||
page: 'pages/index/index',
|
page: 'pages/index/index',
|
||||||
scene: scene,
|
scene: scene,
|
||||||
width: 430,
|
width: 180,
|
||||||
checkPath: true,
|
checkPath: true,
|
||||||
envVersion: 'release'
|
envVersion: 'trial'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -99,3 +99,17 @@ export async function getShopCoupon(id: number) {
|
|||||||
}
|
}
|
||||||
return Promise.reject(new Error(res.message));
|
return Promise.reject(new Error(res.message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 领取优惠券
|
||||||
|
*/
|
||||||
|
export async function receiveCoupon(params: { couponId: number; userId: number }) {
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
'/shop/shop-coupon/receive',
|
||||||
|
params
|
||||||
|
);
|
||||||
|
if (res.code === 0) {
|
||||||
|
return res.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.message));
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ const PaymentCountdown: React.FC<PaymentCountdownProps> = ({
|
|||||||
createTime,
|
createTime,
|
||||||
payStatus = false,
|
payStatus = false,
|
||||||
realTime = false,
|
realTime = false,
|
||||||
timeoutHours = 24,
|
timeoutHours = 1,
|
||||||
showSeconds = false,
|
showSeconds = false,
|
||||||
className = '',
|
className = '',
|
||||||
onExpired,
|
onExpired,
|
||||||
@@ -47,17 +47,10 @@ const PaymentCountdown: React.FC<PaymentCountdownProps> = ({
|
|||||||
// 如果已过期,触发回调并显示过期状态
|
// 如果已过期,触发回调并显示过期状态
|
||||||
if (timeLeft.isExpired) {
|
if (timeLeft.isExpired) {
|
||||||
onExpired?.();
|
onExpired?.();
|
||||||
if (mode === 'text') {
|
|
||||||
return (
|
|
||||||
<Text className={`payment-countdown-text expired ${className}`}>
|
|
||||||
支付已过期
|
|
||||||
</Text>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<View className={`payment-countdown-badge expired ${className}`}>
|
<Text className={`payment-countdown-text expired ${className}`}>
|
||||||
<Text className="countdown-text">支付已过期</Text>
|
支付已过期
|
||||||
</View>
|
</Text>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ const SimpleQRCodeModal: React.FC<SimpleQRCodeModalProps> = ({
|
|||||||
{qrContent ? (
|
{qrContent ? (
|
||||||
<View className={'flex flex-col justify-center'}>
|
<View className={'flex flex-col justify-center'}>
|
||||||
<img
|
<img
|
||||||
src={`http://127.0.0.1:9200/api/qr-code/create-encrypted-qr-image?size=300x300&expireMinutes=60&businessType=gift&data=${encodeURIComponent(qrContent)}`}
|
src={`https://cms-api.websoft.top/api/qr-code/create-encrypted-qr-image?size=300x300&expireMinutes=60&businessType=gift&data=${encodeURIComponent(qrContent)}`}
|
||||||
alt="二维码"
|
alt="二维码"
|
||||||
style={{width: '200px', height: '200px'}}
|
style={{width: '200px', height: '200px'}}
|
||||||
className="mx-auto"
|
className="mx-auto"
|
||||||
|
|||||||
510
src/coupon/index.tsx
Normal file
510
src/coupon/index.tsx
Normal file
@@ -0,0 +1,510 @@
|
|||||||
|
import {useState} from "react";
|
||||||
|
import Taro, {useDidShow} from '@tarojs/taro'
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Empty,
|
||||||
|
ConfigProvider,
|
||||||
|
SearchBar,
|
||||||
|
InfiniteLoading,
|
||||||
|
Loading,
|
||||||
|
PullToRefresh,
|
||||||
|
Tabs,
|
||||||
|
TabPane,
|
||||||
|
Swiper,
|
||||||
|
SwiperItem
|
||||||
|
} from '@nutui/nutui-react-taro'
|
||||||
|
import {Filter, Board, Gift} from '@nutui/icons-react-taro'
|
||||||
|
import {View} from '@tarojs/components'
|
||||||
|
import {ShopCoupon} from "@/api/shop/shopCoupon/model";
|
||||||
|
import {pageShopCoupon, receiveCoupon} from "@/api/shop/shopCoupon";
|
||||||
|
import CouponList from "@/components/CouponList";
|
||||||
|
import CouponGuide from "@/components/CouponGuide";
|
||||||
|
import CouponFilter from "@/components/CouponFilter";
|
||||||
|
import {CouponCardProps} from "@/components/CouponCard";
|
||||||
|
|
||||||
|
const CouponReceiveCenter = () => {
|
||||||
|
const [list, setList] = useState<ShopCoupon[]>([])
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [hasMore, setHasMore] = useState(true)
|
||||||
|
const [searchValue, setSearchValue] = useState('')
|
||||||
|
const [page, setPage] = useState(1)
|
||||||
|
const [activeTab, setActiveTab] = useState('0') // 0-全部 1-满减券 2-折扣券 3-免费券
|
||||||
|
const [hotCoupons, setHotCoupons] = useState<ShopCoupon[]>([]) // 热门优惠券
|
||||||
|
const [showGuide, setShowGuide] = useState(false)
|
||||||
|
const [showFilter, setShowFilter] = useState(false)
|
||||||
|
const [filters, setFilters] = useState({
|
||||||
|
type: [] as number[],
|
||||||
|
minAmount: undefined as number | undefined,
|
||||||
|
sortBy: 'createTime' as 'createTime' | 'amount' | 'expireTime',
|
||||||
|
sortOrder: 'desc' as 'asc' | 'desc'
|
||||||
|
})
|
||||||
|
|
||||||
|
// 获取优惠券类型过滤条件
|
||||||
|
const getTypeFilter = () => {
|
||||||
|
switch (String(activeTab)) {
|
||||||
|
case '0': // 全部
|
||||||
|
return {}
|
||||||
|
case '1': // 满减券
|
||||||
|
return { type: 10 }
|
||||||
|
case '2': // 折扣券
|
||||||
|
return { type: 20 }
|
||||||
|
case '3': // 免费券
|
||||||
|
return { type: 30 }
|
||||||
|
default:
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据传入的值获取类型过滤条件
|
||||||
|
const getTypeFilterByValue = (value: string | number) => {
|
||||||
|
switch (String(value)) {
|
||||||
|
case '0': // 全部
|
||||||
|
return {}
|
||||||
|
case '1': // 满减券
|
||||||
|
return { type: 10 }
|
||||||
|
case '2': // 折扣券
|
||||||
|
return { type: 20 }
|
||||||
|
case '3': // 免费券
|
||||||
|
return { type: 30 }
|
||||||
|
default:
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据类型过滤条件加载优惠券
|
||||||
|
const loadCouponsByType = async (typeFilter: any) => {
|
||||||
|
setLoading(true)
|
||||||
|
try {
|
||||||
|
const currentPage = 1
|
||||||
|
// 获取可领取的优惠券(启用状态且未过期)
|
||||||
|
const res = await pageShopCoupon({
|
||||||
|
page: currentPage,
|
||||||
|
limit: 10,
|
||||||
|
keywords: searchValue,
|
||||||
|
enabled: 1, // 启用状态
|
||||||
|
isExpire: 0, // 未过期
|
||||||
|
...typeFilter
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('API返回数据:', res)
|
||||||
|
if (res && res.list) {
|
||||||
|
setList(res.list)
|
||||||
|
setHasMore(res.list.length === 10)
|
||||||
|
setPage(2)
|
||||||
|
} else {
|
||||||
|
setList([])
|
||||||
|
setHasMore(false)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取优惠券失败:', error)
|
||||||
|
Taro.showToast({
|
||||||
|
title: '获取优惠券失败',
|
||||||
|
icon: 'error'
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const reload = async (isRefresh = false) => {
|
||||||
|
if (isRefresh) {
|
||||||
|
setPage(1)
|
||||||
|
setList([])
|
||||||
|
setHasMore(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(true)
|
||||||
|
try {
|
||||||
|
const currentPage = isRefresh ? 1 : page
|
||||||
|
const typeFilter = getTypeFilter()
|
||||||
|
console.log('reload - 当前activeTab:', activeTab, '类型过滤:', typeFilter)
|
||||||
|
|
||||||
|
// 获取可领取的优惠券(启用状态且未过期)
|
||||||
|
const res = await pageShopCoupon({
|
||||||
|
page: currentPage,
|
||||||
|
limit: 10,
|
||||||
|
keywords: searchValue,
|
||||||
|
enabled: 1, // 启用状态
|
||||||
|
isExpire: 0, // 未过期
|
||||||
|
...typeFilter,
|
||||||
|
// 应用筛选条件
|
||||||
|
...(filters.type.length > 0 && { type: filters.type[0] }),
|
||||||
|
sortBy: filters.sortBy,
|
||||||
|
sortOrder: filters.sortOrder
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('reload - API返回数据:', res)
|
||||||
|
if (res && res.list) {
|
||||||
|
const newList = isRefresh ? res.list : [...list, ...res.list]
|
||||||
|
setList(newList)
|
||||||
|
|
||||||
|
// 判断是否还有更多数据
|
||||||
|
setHasMore(res.list.length === 10)
|
||||||
|
|
||||||
|
if (!isRefresh) {
|
||||||
|
setPage(currentPage + 1)
|
||||||
|
} else {
|
||||||
|
setPage(2)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setHasMore(false)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取优惠券失败:', error)
|
||||||
|
Taro.showToast({
|
||||||
|
title: '获取优惠券失败',
|
||||||
|
icon: 'error'
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索功能
|
||||||
|
const handleSearch = (value: string) => {
|
||||||
|
setSearchValue(value)
|
||||||
|
reload(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下拉刷新
|
||||||
|
const handleRefresh = async () => {
|
||||||
|
await reload(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tab切换
|
||||||
|
const handleTabChange = (value: string | number) => {
|
||||||
|
console.log('Tab切换到:', value)
|
||||||
|
setActiveTab(String(value))
|
||||||
|
setPage(1)
|
||||||
|
setList([])
|
||||||
|
setHasMore(true)
|
||||||
|
|
||||||
|
// 直接传递类型值,避免异步状态更新问题
|
||||||
|
const typeFilter = getTypeFilterByValue(value)
|
||||||
|
console.log('类型过滤条件:', typeFilter)
|
||||||
|
|
||||||
|
// 立即加载数据
|
||||||
|
loadCouponsByType(typeFilter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载热门优惠券
|
||||||
|
const loadHotCoupons = async () => {
|
||||||
|
try {
|
||||||
|
const res = await pageShopCoupon({
|
||||||
|
page: 1,
|
||||||
|
limit: 5,
|
||||||
|
enabled: 1,
|
||||||
|
isExpire: 0,
|
||||||
|
sortBy: 'createTime',
|
||||||
|
sortOrder: 'desc'
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res && res.list) {
|
||||||
|
setHotCoupons(res.list)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取热门优惠券失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换优惠券数据为CouponCard组件所需格式
|
||||||
|
const transformCouponData = (coupon: ShopCoupon): CouponCardProps => {
|
||||||
|
let amount = 0
|
||||||
|
let type: 10 | 20 | 30 = 10
|
||||||
|
|
||||||
|
if (coupon.type === 10) { // 满减券
|
||||||
|
type = 10
|
||||||
|
amount = parseFloat(coupon.reducePrice || '0')
|
||||||
|
} else if (coupon.type === 20) { // 折扣券
|
||||||
|
type = 20
|
||||||
|
amount = coupon.discount || 0
|
||||||
|
} else if (coupon.type === 30) { // 免费券
|
||||||
|
type = 30
|
||||||
|
amount = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: coupon.id?.toString(),
|
||||||
|
amount,
|
||||||
|
type,
|
||||||
|
status: 0, // 可领取状态
|
||||||
|
minAmount: parseFloat(coupon.minPrice || '0'),
|
||||||
|
title: coupon.name || '优惠券',
|
||||||
|
description: coupon.description,
|
||||||
|
startTime: coupon.startTime,
|
||||||
|
endTime: coupon.endTime,
|
||||||
|
showReceiveBtn: true, // 显示领取按钮
|
||||||
|
onReceive: () => handleReceiveCoupon(coupon),
|
||||||
|
theme: getThemeByType(coupon.type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据优惠券类型获取主题色
|
||||||
|
const getThemeByType = (type?: number): 'red' | 'orange' | 'blue' | 'purple' | 'green' => {
|
||||||
|
switch (type) {
|
||||||
|
case 10: return 'red' // 满减券-红色
|
||||||
|
case 20: return 'orange' // 折扣券-橙色
|
||||||
|
case 30: return 'green' // 免费券-绿色
|
||||||
|
default: return 'blue'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 领取优惠券
|
||||||
|
const handleReceiveCoupon = async (coupon: ShopCoupon) => {
|
||||||
|
try {
|
||||||
|
// 检查是否已登录
|
||||||
|
const userId = Taro.getStorageSync('UserId')
|
||||||
|
if (!userId) {
|
||||||
|
Taro.showToast({
|
||||||
|
title: '请先登录',
|
||||||
|
icon: 'error'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用领取接口
|
||||||
|
await receiveCoupon({
|
||||||
|
couponId: coupon.id!,
|
||||||
|
userId: userId
|
||||||
|
})
|
||||||
|
|
||||||
|
Taro.showToast({
|
||||||
|
title: '领取成功',
|
||||||
|
icon: 'success'
|
||||||
|
})
|
||||||
|
|
||||||
|
// 刷新列表
|
||||||
|
reload(true)
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('领取优惠券失败:', error)
|
||||||
|
Taro.showToast({
|
||||||
|
title: error.message || '领取失败',
|
||||||
|
icon: 'error'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 优惠券点击事件
|
||||||
|
const handleCouponClick = (_: CouponCardProps, index: number) => {
|
||||||
|
const originalCoupon = list[index]
|
||||||
|
if (originalCoupon) {
|
||||||
|
// 显示优惠券详情
|
||||||
|
handleCouponDetail(originalCoupon)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示优惠券详情
|
||||||
|
const handleCouponDetail = (coupon: ShopCoupon) => {
|
||||||
|
// 可以显示优惠券详情弹窗或跳转到详情页
|
||||||
|
Taro.showModal({
|
||||||
|
title: coupon.name || '优惠券详情',
|
||||||
|
content: `${coupon.description || ''}
|
||||||
|
|
||||||
|
优惠类型:${coupon.type === 10 ? '满减券' : coupon.type === 20 ? '折扣券' : '免费券'}
|
||||||
|
${coupon.minPrice ? `最低消费:¥${coupon.minPrice}` : ''}
|
||||||
|
有效期:${coupon.startTime} 至 ${coupon.endTime}`,
|
||||||
|
showCancel: false,
|
||||||
|
confirmText: '知道了'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 筛选条件变更
|
||||||
|
const handleFiltersChange = (newFilters: any) => {
|
||||||
|
setFilters(newFilters)
|
||||||
|
reload(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查看我的优惠券
|
||||||
|
const handleViewMyCoupons = () => {
|
||||||
|
Taro.navigateTo({
|
||||||
|
url: '/user/coupon/index'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载更多
|
||||||
|
const loadMore = async () => {
|
||||||
|
if (!loading && hasMore) {
|
||||||
|
await reload(false) // 不刷新,追加数据
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useDidShow(() => {
|
||||||
|
reload(true)
|
||||||
|
loadHotCoupons()
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConfigProvider>
|
||||||
|
{/* 搜索栏和功能入口 */}
|
||||||
|
<View className="bg-white px-4 py-3">
|
||||||
|
<View className="flex items-center justify-between gap-3">
|
||||||
|
<View className="flex-1">
|
||||||
|
<SearchBar
|
||||||
|
placeholder="搜索优惠券"
|
||||||
|
value={searchValue}
|
||||||
|
className={'border'}
|
||||||
|
onChange={setSearchValue}
|
||||||
|
onSearch={handleSearch}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
fill="outline"
|
||||||
|
icon={<Filter />}
|
||||||
|
onClick={() => setShowFilter(true)}
|
||||||
|
>
|
||||||
|
筛选
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
fill="outline"
|
||||||
|
icon={<Board />}
|
||||||
|
onClick={() => setShowGuide(true)}
|
||||||
|
>
|
||||||
|
帮助
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* 热门优惠券轮播 */}
|
||||||
|
{hotCoupons.length > 0 && (
|
||||||
|
<View className="bg-white mb-2">
|
||||||
|
<View className="px-4 py-2 text-sm font-medium text-gray-700">🔥 热门推荐</View>
|
||||||
|
<Swiper
|
||||||
|
height={120}
|
||||||
|
autoPlay
|
||||||
|
loop
|
||||||
|
indicator
|
||||||
|
className="px-4 pb-3"
|
||||||
|
>
|
||||||
|
{hotCoupons.map((coupon, index) => (
|
||||||
|
<SwiperItem key={index}>
|
||||||
|
<View
|
||||||
|
className="bg-gradient-to-r from-red-400 to-pink-500 rounded-lg p-4 text-white mr-4"
|
||||||
|
onClick={() => handleCouponDetail(coupon)}
|
||||||
|
>
|
||||||
|
<View className="flex justify-between items-center">
|
||||||
|
<View>
|
||||||
|
<View className="text-lg font-bold">
|
||||||
|
{coupon.type === 10 ? `¥${coupon.reducePrice}` :
|
||||||
|
coupon.type === 20 ? `${coupon.discount}折` : '免费'}
|
||||||
|
</View>
|
||||||
|
<View className="text-sm opacity-90">
|
||||||
|
{coupon.name}
|
||||||
|
</View>
|
||||||
|
{coupon.minPrice && (
|
||||||
|
<View className="text-xs opacity-80">
|
||||||
|
满¥{coupon.minPrice}可用
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
className="bg-white text-red-500 border-0"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
handleReceiveCoupon(coupon)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
立即领取
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</SwiperItem>
|
||||||
|
))}
|
||||||
|
</Swiper>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Tab切换 */}
|
||||||
|
<View className="bg-white">
|
||||||
|
<Tabs value={activeTab} onChange={handleTabChange}>
|
||||||
|
<TabPane title="全部" value="0">
|
||||||
|
</TabPane>
|
||||||
|
<TabPane title="满减券" value="1">
|
||||||
|
</TabPane>
|
||||||
|
<TabPane title="折扣券" value="2">
|
||||||
|
</TabPane>
|
||||||
|
<TabPane title="免费券" value="3">
|
||||||
|
</TabPane>
|
||||||
|
</Tabs>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* 优惠券列表 */}
|
||||||
|
<PullToRefresh
|
||||||
|
onRefresh={handleRefresh}
|
||||||
|
headHeight={60}
|
||||||
|
>
|
||||||
|
<View style={{ height: '600px', overflowY: 'auto' }} id="coupon-scroll">
|
||||||
|
{list.length === 0 && !loading ? (
|
||||||
|
<View className="flex flex-col justify-center items-center" style={{height: '500px'}}>
|
||||||
|
<Empty
|
||||||
|
description="暂无可领取的优惠券"
|
||||||
|
style={{backgroundColor: 'transparent'}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
<InfiniteLoading
|
||||||
|
target="coupon-scroll"
|
||||||
|
hasMore={hasMore}
|
||||||
|
onLoadMore={loadMore}
|
||||||
|
loadingText={
|
||||||
|
<View className="flex justify-center items-center py-4">
|
||||||
|
<Loading />
|
||||||
|
<View className="ml-2">加载中...</View>
|
||||||
|
</View>
|
||||||
|
}
|
||||||
|
loadMoreText={
|
||||||
|
<View className="text-center py-4 text-gray-500">
|
||||||
|
{list.length === 0 ? "暂无数据" : "没有更多了"}
|
||||||
|
</View>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<CouponList
|
||||||
|
coupons={list.map(transformCouponData)}
|
||||||
|
onCouponClick={handleCouponClick}
|
||||||
|
showEmpty={false}
|
||||||
|
/>
|
||||||
|
</InfiniteLoading>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</PullToRefresh>
|
||||||
|
|
||||||
|
{/* 底部提示 */}
|
||||||
|
{list.length === 0 && !loading && (
|
||||||
|
<View className="text-center py-8">
|
||||||
|
<View className="text-gray-400 mb-4">
|
||||||
|
<Gift size="48" />
|
||||||
|
</View>
|
||||||
|
<View className="text-gray-500 mb-2">暂无可领取的优惠券</View>
|
||||||
|
<View className="flex gap-2 justify-center">
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
onClick={handleViewMyCoupons}
|
||||||
|
>
|
||||||
|
查看我的优惠券
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* 使用指南弹窗 */}
|
||||||
|
<CouponGuide
|
||||||
|
visible={showGuide}
|
||||||
|
onClose={() => setShowGuide(false)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 筛选弹窗 */}
|
||||||
|
<CouponFilter
|
||||||
|
visible={showFilter}
|
||||||
|
filters={filters}
|
||||||
|
onFiltersChange={handleFiltersChange}
|
||||||
|
onClose={() => setShowFilter(false)}
|
||||||
|
/>
|
||||||
|
</ConfigProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CouponReceiveCenter;
|
||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
const AddUserAddress = () => {
|
const AddUserAddress = () => {
|
||||||
const {user} = useUser()
|
const {user} = useUser()
|
||||||
const [loading, setLoading] = useState<boolean>(true)
|
const [loading, setLoading] = useState<boolean>(true)
|
||||||
const [FormData, setFormData] = useState<ShopDealerApply>({})
|
const [FormData, setFormData] = useState<ShopDealerApply>()
|
||||||
const formRef = useRef<any>(null)
|
const formRef = useRef<any>(null)
|
||||||
const [isEditMode, setIsEditMode] = useState<boolean>(false)
|
const [isEditMode, setIsEditMode] = useState<boolean>(false)
|
||||||
const [existingApply, setExistingApply] = useState<ShopDealerApply | null>(null)
|
const [existingApply, setExistingApply] = useState<ShopDealerApply | null>(null)
|
||||||
@@ -47,16 +47,17 @@ const AddUserAddress = () => {
|
|||||||
setExistingApply(res.list[0]);
|
setExistingApply(res.list[0]);
|
||||||
// 如果有记录,填充表单数据
|
// 如果有记录,填充表单数据
|
||||||
setFormData(res.list[0]);
|
setFormData(res.list[0]);
|
||||||
|
setLoading(false)
|
||||||
} else {
|
} else {
|
||||||
setFormData({})
|
|
||||||
setIsEditMode(false);
|
setIsEditMode(false);
|
||||||
setExistingApply(null);
|
setExistingApply(null);
|
||||||
|
setLoading(false)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
setLoading(true)
|
||||||
console.error('查询申请记录失败:', error);
|
console.error('查询申请记录失败:', error);
|
||||||
setIsEditMode(false);
|
setIsEditMode(false);
|
||||||
setExistingApply(null);
|
setExistingApply(null);
|
||||||
setFormData({})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +123,11 @@ const AddUserAddress = () => {
|
|||||||
if (loading) {
|
if (loading) {
|
||||||
return <Loading className={'px-2'}>加载中</Loading>
|
return <Loading className={'px-2'}>加载中</Loading>
|
||||||
}
|
}
|
||||||
|
console.log(FormData,'FromData')
|
||||||
|
|
||||||
|
if(!FormData){
|
||||||
|
return <Loading className={'px-2'}>加载中</Loading>
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Form
|
<Form
|
||||||
@@ -153,29 +158,29 @@ const AddUserAddress = () => {
|
|||||||
title={'审核状态'}
|
title={'审核状态'}
|
||||||
extra={
|
extra={
|
||||||
<span style={{
|
<span style={{
|
||||||
color: FormData.applyStatus === 20 ? '#52c41a' :
|
color: FormData?.applyStatus === 20 ? '#52c41a' :
|
||||||
FormData.applyStatus === 30 ? '#ff4d4f' : '#faad14'
|
FormData?.applyStatus === 30 ? '#ff4d4f' : '#faad14'
|
||||||
}}>
|
}}>
|
||||||
{getApplyStatusText(FormData.applyStatus)}
|
{getApplyStatusText(FormData?.applyStatus)}
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{FormData.applyStatus === 20 && (
|
{FormData?.applyStatus === 20 && (
|
||||||
<Cell title={'审核时间'} extra={FormData.auditTime || '无'}/>
|
<Cell title={'审核时间'} extra={FormData?.auditTime || '无'}/>
|
||||||
)}
|
)}
|
||||||
{FormData.applyStatus === 30 && (
|
{FormData?.applyStatus === 30 && (
|
||||||
<Cell title={'驳回原因'} extra={FormData.rejectReason || '无'}/>
|
<Cell title={'驳回原因'} extra={FormData?.rejectReason || '无'}/>
|
||||||
)}
|
)}
|
||||||
</CellGroup>
|
</CellGroup>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
||||||
{/* 底部浮动按钮 */}
|
{/* 底部浮动按钮 */}
|
||||||
{(!isEditMode || FormData.applyStatus === 10 || FormData.applyStatus === 30) && (
|
{(!isEditMode || FormData?.applyStatus === 10 || FormData?.applyStatus === 30) && (
|
||||||
<FixedButton
|
<FixedButton
|
||||||
icon={<Edit/>}
|
icon={<Edit/>}
|
||||||
text={isEditMode ? '保存修改' : '提交申请'}
|
text={isEditMode ? '保存修改' : '提交申请'}
|
||||||
disabled={FormData.applyStatus === 10}
|
disabled={FormData?.applyStatus === 10}
|
||||||
onClick={handleFixedButtonClick}
|
onClick={handleFixedButtonClick}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ import {
|
|||||||
Dongdong,
|
Dongdong,
|
||||||
ArrowRight,
|
ArrowRight,
|
||||||
Purse,
|
Purse,
|
||||||
People,
|
People
|
||||||
Presentation
|
|
||||||
} from '@nutui/icons-react-taro'
|
} from '@nutui/icons-react-taro'
|
||||||
import {useDealerUser} from '@/hooks/useDealerUser'
|
import {useDealerUser} from '@/hooks/useDealerUser'
|
||||||
import { useThemeStyles } from '@/hooks/useTheme'
|
import { useThemeStyles } from '@/hooks/useTheme'
|
||||||
@@ -244,45 +243,45 @@ const DealerIndex: React.FC = () => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
{/* 第二行功能 */}
|
{/* 第二行功能 */}
|
||||||
<Grid
|
{/*<Grid*/}
|
||||||
columns={4}
|
{/* columns={4}*/}
|
||||||
className="no-border-grid mt-4"
|
{/* className="no-border-grid mt-4"*/}
|
||||||
style={{
|
{/* style={{*/}
|
||||||
'--nutui-grid-border-color': 'transparent',
|
{/* '--nutui-grid-border-color': 'transparent',*/}
|
||||||
'--nutui-grid-item-border-width': '0px',
|
{/* '--nutui-grid-item-border-width': '0px',*/}
|
||||||
border: 'none'
|
{/* border: 'none'*/}
|
||||||
} as React.CSSProperties}
|
{/* } as React.CSSProperties}*/}
|
||||||
>
|
{/*>*/}
|
||||||
<Grid.Item text={'邀请统计'} onClick={() => navigateToPage('/dealer/invite-stats/index')}>
|
{/* <Grid.Item text={'邀请统计'} onClick={() => navigateToPage('/dealer/invite-stats/index')}>*/}
|
||||||
<View className="text-center">
|
{/* <View className="text-center">*/}
|
||||||
<View className="w-12 h-12 bg-indigo-50 rounded-xl flex items-center justify-center mx-auto mb-2">
|
{/* <View className="w-12 h-12 bg-indigo-50 rounded-xl flex items-center justify-center mx-auto mb-2">*/}
|
||||||
<Presentation color="#6366f1" size="20"/>
|
{/* <Presentation color="#6366f1" size="20"/>*/}
|
||||||
</View>
|
{/* </View>*/}
|
||||||
</View>
|
{/* </View>*/}
|
||||||
</Grid.Item>
|
{/* </Grid.Item>*/}
|
||||||
|
|
||||||
{/* 预留其他功能位置 */}
|
{/* /!* 预留其他功能位置 *!/*/}
|
||||||
<Grid.Item text={''}>
|
{/* <Grid.Item text={''}>*/}
|
||||||
<View className="text-center">
|
{/* <View className="text-center">*/}
|
||||||
<View className="w-12 h-12 bg-gray-50 rounded-xl flex items-center justify-center mx-auto mb-2">
|
{/* <View className="w-12 h-12 bg-gray-50 rounded-xl flex items-center justify-center mx-auto mb-2">*/}
|
||||||
</View>
|
{/* </View>*/}
|
||||||
</View>
|
{/* </View>*/}
|
||||||
</Grid.Item>
|
{/* </Grid.Item>*/}
|
||||||
|
|
||||||
<Grid.Item text={''}>
|
{/* <Grid.Item text={''}>*/}
|
||||||
<View className="text-center">
|
{/* <View className="text-center">*/}
|
||||||
<View className="w-12 h-12 bg-gray-50 rounded-xl flex items-center justify-center mx-auto mb-2">
|
{/* <View className="w-12 h-12 bg-gray-50 rounded-xl flex items-center justify-center mx-auto mb-2">*/}
|
||||||
</View>
|
{/* </View>*/}
|
||||||
</View>
|
{/* </View>*/}
|
||||||
</Grid.Item>
|
{/* </Grid.Item>*/}
|
||||||
|
|
||||||
<Grid.Item text={''}>
|
{/* <Grid.Item text={''}>*/}
|
||||||
<View className="text-center">
|
{/* <View className="text-center">*/}
|
||||||
<View className="w-12 h-12 bg-gray-50 rounded-xl flex items-center justify-center mx-auto mb-2">
|
{/* <View className="w-12 h-12 bg-gray-50 rounded-xl flex items-center justify-center mx-auto mb-2">*/}
|
||||||
</View>
|
{/* </View>*/}
|
||||||
</View>
|
{/* </View>*/}
|
||||||
</Grid.Item>
|
{/* </Grid.Item>*/}
|
||||||
</Grid>
|
{/*</Grid>*/}
|
||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
import React, { useState, useEffect } from 'react'
|
import React, {useState, useEffect} from 'react'
|
||||||
import { View, Text, Image } from '@tarojs/components'
|
import {View, Text, Image} from '@tarojs/components'
|
||||||
import { Button, Loading } from '@nutui/nutui-react-taro'
|
import {Button, Loading} from '@nutui/nutui-react-taro'
|
||||||
import { Share, Download, Copy, QrCode } from '@nutui/icons-react-taro'
|
import {Share, Download, Copy, QrCode} from '@nutui/icons-react-taro'
|
||||||
import Taro from '@tarojs/taro'
|
import Taro from '@tarojs/taro'
|
||||||
import { useDealerUser } from '@/hooks/useDealerUser'
|
import {useDealerUser} from '@/hooks/useDealerUser'
|
||||||
import { generateInviteCode, getInviteStats } from '@/api/invite'
|
import {generateInviteCode, getInviteStats} from '@/api/invite'
|
||||||
import type { InviteStats } from '@/api/invite'
|
import type {InviteStats} from '@/api/invite'
|
||||||
import { businessGradients } from '@/styles/gradients'
|
import {businessGradients} from '@/styles/gradients'
|
||||||
|
|
||||||
const DealerQrcode: React.FC = () => {
|
const DealerQrcode: React.FC = () => {
|
||||||
const [miniProgramCodeUrl, setMiniProgramCodeUrl] = useState<string>('')
|
const [miniProgramCodeUrl, setMiniProgramCodeUrl] = useState<string>('')
|
||||||
const [loading, setLoading] = useState<boolean>(false)
|
const [loading, setLoading] = useState<boolean>(false)
|
||||||
const [inviteStats, setInviteStats] = useState<InviteStats | null>(null)
|
const [inviteStats, setInviteStats] = useState<InviteStats | null>(null)
|
||||||
const [statsLoading, setStatsLoading] = useState<boolean>(false)
|
const [statsLoading, setStatsLoading] = useState<boolean>(false)
|
||||||
const { dealerUser } = useDealerUser()
|
const {dealerUser} = useDealerUser()
|
||||||
|
|
||||||
// 生成小程序码
|
// 生成小程序码
|
||||||
const generateMiniProgramCode = async () => {
|
const generateMiniProgramCode = async () => {
|
||||||
@@ -23,8 +23,8 @@ const DealerQrcode: React.FC = () => {
|
|||||||
setLoading(true)
|
setLoading(true)
|
||||||
|
|
||||||
// 生成邀请小程序码
|
// 生成邀请小程序码
|
||||||
const codeUrl = await generateInviteCode(dealerUser.userId, 'qrcode')
|
const codeUrl = await generateInviteCode(dealerUser.userId)
|
||||||
|
console.log('小程序码生成成功:', codeUrl)
|
||||||
if (codeUrl) {
|
if (codeUrl) {
|
||||||
setMiniProgramCodeUrl(codeUrl)
|
setMiniProgramCodeUrl(codeUrl)
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@ const DealerQrcode: React.FC = () => {
|
|||||||
if (!dealerUser) {
|
if (!dealerUser) {
|
||||||
return (
|
return (
|
||||||
<View className="bg-gray-50 min-h-screen flex items-center justify-center">
|
<View className="bg-gray-50 min-h-screen flex items-center justify-center">
|
||||||
<Loading />
|
<Loading/>
|
||||||
<Text className="text-gray-500 mt-2">加载中...</Text>
|
<Text className="text-gray-500 mt-2">加载中...</Text>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
@@ -179,7 +179,7 @@ const DealerQrcode: React.FC = () => {
|
|||||||
right: '-16px'
|
right: '-16px'
|
||||||
}}></View>
|
}}></View>
|
||||||
|
|
||||||
<View className="relative z-10">
|
<View className="relative z-10 flex flex-col">
|
||||||
<Text className="text-2xl font-bold mb-2 text-white">我的邀请小程序码</Text>
|
<Text className="text-2xl font-bold mb-2 text-white">我的邀请小程序码</Text>
|
||||||
<Text className="text-white text-opacity-80">
|
<Text className="text-white text-opacity-80">
|
||||||
分享小程序码邀请好友,获得丰厚佣金奖励
|
分享小程序码邀请好友,获得丰厚佣金奖励
|
||||||
@@ -189,11 +189,16 @@ const DealerQrcode: React.FC = () => {
|
|||||||
|
|
||||||
<View className="px-4">
|
<View className="px-4">
|
||||||
{/* 小程序码展示区 */}
|
{/* 小程序码展示区 */}
|
||||||
|
{/*<Image*/}
|
||||||
|
{/* src={'http://127.0.0.1:9200/api/wx-login/getOrderQRCodeUnlimited/33103'}*/}
|
||||||
|
{/* className="w-full h-full"*/}
|
||||||
|
{/* mode="aspectFit"*/}
|
||||||
|
{/*/>*/}
|
||||||
<View className="bg-white rounded-2xl p-6 mb-6 shadow-sm">
|
<View className="bg-white rounded-2xl p-6 mb-6 shadow-sm">
|
||||||
<View className="text-center">
|
<View className="text-center">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<View className="w-48 h-48 mx-auto mb-4 flex items-center justify-center bg-gray-50 rounded-xl">
|
<View className="w-48 h-48 mx-auto mb-4 flex items-center justify-center bg-gray-50 rounded-xl">
|
||||||
<Loading />
|
<Loading/>
|
||||||
<Text className="text-gray-500 mt-2">生成中...</Text>
|
<Text className="text-gray-500 mt-2">生成中...</Text>
|
||||||
</View>
|
</View>
|
||||||
) : miniProgramCodeUrl ? (
|
) : miniProgramCodeUrl ? (
|
||||||
@@ -219,48 +224,52 @@ const DealerQrcode: React.FC = () => {
|
|||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Text className="text-lg font-semibold text-gray-800 mb-2">
|
<View className="text-lg font-semibold text-gray-800 mb-2">
|
||||||
扫码加入我的团队
|
扫码加入我的团队
|
||||||
</Text>
|
</View>
|
||||||
<Text className="text-sm text-gray-500 mb-6">
|
<View className="text-sm text-gray-500 mb-6">
|
||||||
好友扫描小程序码即可直接进入小程序并建立邀请关系
|
好友扫描小程序码即可直接进入小程序并建立邀请关系
|
||||||
</Text>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* 操作按钮 */}
|
{/* 操作按钮 */}
|
||||||
<View className="space-y-3">
|
<View className={'gap-2'}>
|
||||||
<Button
|
<View className={'my-2'}>
|
||||||
type="primary"
|
<Button
|
||||||
size="large"
|
type="primary"
|
||||||
block
|
size="large"
|
||||||
icon={<Download />}
|
block
|
||||||
onClick={saveMiniProgramCode}
|
icon={<Download/>}
|
||||||
disabled={!miniProgramCodeUrl || loading}
|
onClick={saveMiniProgramCode}
|
||||||
>
|
disabled={!miniProgramCodeUrl || loading}
|
||||||
保存小程序码到相册
|
>
|
||||||
</Button>
|
保存小程序码到相册
|
||||||
|
</Button>
|
||||||
<Button
|
</View>
|
||||||
size="large"
|
<View className={'my-2 bg-white'}>
|
||||||
block
|
<Button
|
||||||
icon={<Copy />}
|
size="large"
|
||||||
onClick={copyInviteInfo}
|
block
|
||||||
disabled={!dealerUser?.userId || loading}
|
icon={<Copy/>}
|
||||||
>
|
onClick={copyInviteInfo}
|
||||||
复制邀请信息
|
disabled={!dealerUser?.userId || loading}
|
||||||
</Button>
|
>
|
||||||
|
复制邀请信息
|
||||||
<Button
|
</Button>
|
||||||
size="large"
|
</View>
|
||||||
block
|
<View className={'my-2 bg-white'}>
|
||||||
fill="outline"
|
<Button
|
||||||
icon={<Share />}
|
size="large"
|
||||||
onClick={shareMiniProgramCode}
|
block
|
||||||
disabled={!dealerUser?.userId || loading}
|
fill="outline"
|
||||||
>
|
icon={<Share/>}
|
||||||
分享给好友
|
onClick={shareMiniProgramCode}
|
||||||
</Button>
|
disabled={!dealerUser?.userId || loading}
|
||||||
|
>
|
||||||
|
分享给好友
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* 推广说明 */}
|
{/* 推广说明 */}
|
||||||
@@ -293,7 +302,7 @@ const DealerQrcode: React.FC = () => {
|
|||||||
<Text className="font-semibold text-gray-800 mb-3">我的邀请数据</Text>
|
<Text className="font-semibold text-gray-800 mb-3">我的邀请数据</Text>
|
||||||
{statsLoading ? (
|
{statsLoading ? (
|
||||||
<View className="flex items-center justify-center py-8">
|
<View className="flex items-center justify-center py-8">
|
||||||
<Loading />
|
<Loading/>
|
||||||
<Text className="text-gray-500 mt-2">加载中...</Text>
|
<Text className="text-gray-500 mt-2">加载中...</Text>
|
||||||
</View>
|
</View>
|
||||||
) : inviteStats ? (
|
) : inviteStats ? (
|
||||||
@@ -353,7 +362,7 @@ const DealerQrcode: React.FC = () => {
|
|||||||
</View>
|
</View>
|
||||||
) : (
|
) : (
|
||||||
<View className="text-center py-8">
|
<View className="text-center py-8">
|
||||||
<Text className="text-gray-500">暂无邀请数据</Text>
|
<View className="text-gray-500">暂无邀请数据</View>
|
||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
type="primary"
|
type="primary"
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ import {getUserInfo, getWxOpenId} from "@/api/layout";
|
|||||||
import {TenantId} from "@/config/app";
|
import {TenantId} from "@/config/app";
|
||||||
import {getOrganization} from "@/api/system/organization";
|
import {getOrganization} from "@/api/system/organization";
|
||||||
import {myUserVerify} from "@/api/system/userVerify";
|
import {myUserVerify} from "@/api/system/userVerify";
|
||||||
import { useShopInfo } from '@/hooks/useShopInfo';
|
import {useShopInfo} from '@/hooks/useShopInfo';
|
||||||
import {handleInviteRelation} from "@/utils/invite";
|
import {handleInviteRelation} from "@/utils/invite";
|
||||||
|
import {View, Text} from '@tarojs/components'
|
||||||
import MySearch from "./MySearch";
|
import MySearch from "./MySearch";
|
||||||
import './Header.scss';
|
import './Header.scss';
|
||||||
|
|
||||||
@@ -85,7 +86,7 @@ const Header = (props: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 获取用户手机号 */
|
/* 获取用户手机号 */
|
||||||
const handleGetPhoneNumber = ({detail}: {detail: {code?: string, encryptedData?: string, iv?: string}}) => {
|
const handleGetPhoneNumber = ({detail}: { detail: { code?: string, encryptedData?: string, iv?: string } }) => {
|
||||||
const {code, encryptedData, iv} = detail
|
const {code, encryptedData, iv} = detail
|
||||||
Taro.login({
|
Taro.login({
|
||||||
success: function () {
|
success: function () {
|
||||||
@@ -155,39 +156,39 @@ const Header = (props: any) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={'fixed top-0 header-bg'} style={{
|
<View className={'fixed top-0 header-bg'} style={{
|
||||||
height: !props.stickyStatus ? '180px' : '148px',
|
height: !props.stickyStatus ? '180px' : '148px',
|
||||||
}}>
|
}}>
|
||||||
<MySearch/>
|
<MySearch/>
|
||||||
{/*{!props.stickyStatus && <MySearch done={reload}/>}*/}
|
{/*{!props.stickyStatus && <MySearch done={reload}/>}*/}
|
||||||
</div>
|
</View>
|
||||||
<NavBar
|
<NavBar
|
||||||
style={{marginTop: `${statusBarHeight}px`, marginBottom: '0px', backgroundColor: 'transparent'}}
|
style={{marginTop: `${statusBarHeight}px`, marginBottom: '0px', backgroundColor: 'transparent'}}
|
||||||
onBackClick={() => {
|
onBackClick={() => {
|
||||||
}}
|
}}
|
||||||
left={
|
left={
|
||||||
!IsLogin ? (
|
!IsLogin ? (
|
||||||
<div style={{display: 'flex', alignItems: 'center'}}>
|
<Space style={{display: 'flex', alignItems: 'center'}}>
|
||||||
<Button style={{color: '#000'}} open-type="getPhoneNumber" onGetPhoneNumber={handleGetPhoneNumber}>
|
<Button style={{color: '#ffffff'}} open-type="getPhoneNumber" onGetPhoneNumber={handleGetPhoneNumber}>
|
||||||
<Space>
|
<Space>
|
||||||
<Avatar
|
<Avatar
|
||||||
size="22"
|
size="22"
|
||||||
src={getWebsiteLogo()}
|
src={getWebsiteLogo()}
|
||||||
/>
|
/>
|
||||||
<span style={{color: '#000'}}>{getWebsiteName()}</span>
|
<Text style={{color: '#ffffff'}}>{getWebsiteName()}</Text>
|
||||||
</Space>
|
</Space>
|
||||||
</Button>
|
</Button>
|
||||||
<TriangleDown size={9}/>
|
<TriangleDown size={9} className={'text-white'}/>
|
||||||
</div>
|
</Space>
|
||||||
) : (
|
) : (
|
||||||
<div style={{display: 'flex', alignItems: 'center', gap: '8px'}}>
|
<View style={{display: 'flex', alignItems: 'center', gap: '8px'}}>
|
||||||
<Avatar
|
<Avatar
|
||||||
size="22"
|
size="22"
|
||||||
src={getWebsiteLogo()}
|
src={getWebsiteLogo()}
|
||||||
/>
|
/>
|
||||||
<span className={'text-white'}>{getWebsiteName()}</span>
|
<Text className={'text-white'}>{getWebsiteName()}</Text>
|
||||||
<TriangleDown className={'text-white'} size={9}/>
|
<TriangleDown className={'text-white'} size={9}/>
|
||||||
</div>
|
</View>
|
||||||
)}>
|
)}>
|
||||||
</NavBar>
|
</NavBar>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ function UserOrder() {
|
|||||||
<View className={'flex justify-around pb-1 mt-4'}>
|
<View className={'flex justify-around pb-1 mt-4'}>
|
||||||
{/* 待付款 */}
|
{/* 待付款 */}
|
||||||
{orderStats.pending > 0 ? (
|
{orderStats.pending > 0 ? (
|
||||||
<Badge value={orderStats.pending} max={99}>
|
<Badge value={orderStats.pending} max={99} fill={'outline'}>
|
||||||
<View className={'item flex justify-center flex-col items-center'}>
|
<View className={'item flex justify-center flex-col items-center'}>
|
||||||
<Wallet size={26} className={'font-normal text-gray-500'}
|
<Wallet size={26} className={'font-normal text-gray-500'}
|
||||||
onClick={() => navTo('/user/order/order?statusFilter=0', true)}/>
|
onClick={() => navTo('/user/order/order?statusFilter=0', true)}/>
|
||||||
@@ -56,7 +56,7 @@ function UserOrder() {
|
|||||||
|
|
||||||
{/* 待发货 */}
|
{/* 待发货 */}
|
||||||
{orderStats.paid > 0 ? (
|
{orderStats.paid > 0 ? (
|
||||||
<Badge value={orderStats.paid} max={99}>
|
<Badge value={orderStats.paid} max={99} fill={'outline'}>
|
||||||
<View className={'item flex justify-center flex-col items-center'}
|
<View className={'item flex justify-center flex-col items-center'}
|
||||||
onClick={() => navTo('/user/order/order?statusFilter=1', true)}>
|
onClick={() => navTo('/user/order/order?statusFilter=1', true)}>
|
||||||
<Package size={26} className={'text-gray-500 font-normal'}/>
|
<Package size={26} className={'text-gray-500 font-normal'}/>
|
||||||
@@ -73,7 +73,7 @@ function UserOrder() {
|
|||||||
|
|
||||||
{/* 待收货 */}
|
{/* 待收货 */}
|
||||||
{orderStats.shipped > 0 ? (
|
{orderStats.shipped > 0 ? (
|
||||||
<Badge value={orderStats.shipped} max={99}>
|
<Badge value={orderStats.shipped} max={99} fill={'outline'}>
|
||||||
<View className={'item flex justify-center flex-col items-center'}
|
<View className={'item flex justify-center flex-col items-center'}
|
||||||
onClick={() => navTo('/user/order/order?statusFilter=3', true)}>
|
onClick={() => navTo('/user/order/order?statusFilter=3', true)}>
|
||||||
<Transit size={24} className={'text-gray-500 font-normal'}/>
|
<Transit size={24} className={'text-gray-500 font-normal'}/>
|
||||||
@@ -97,7 +97,7 @@ function UserOrder() {
|
|||||||
|
|
||||||
{/* 退货/售后 */}
|
{/* 退货/售后 */}
|
||||||
{orderStats.refund > 0 ? (
|
{orderStats.refund > 0 ? (
|
||||||
<Badge value={orderStats.refund} max={99}>
|
<Badge value={orderStats.refund} max={99} fill={'outline'}>
|
||||||
<View className={'item flex justify-center flex-col items-center'}
|
<View className={'item flex justify-center flex-col items-center'}
|
||||||
onClick={() => navTo('/user/order/order?statusFilter=6', true)}>
|
onClick={() => navTo('/user/order/order?statusFilter=6', true)}>
|
||||||
<Refund size={26} className={'font-normal text-gray-500'}/>
|
<Refund size={26} className={'font-normal text-gray-500'}/>
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import {
|
|||||||
filterUsableCoupons,
|
filterUsableCoupons,
|
||||||
filterUnusableCoupons
|
filterUnusableCoupons
|
||||||
} from "@/utils/couponUtils";
|
} from "@/utils/couponUtils";
|
||||||
|
import navTo from "@/utils/common";
|
||||||
|
|
||||||
|
|
||||||
const OrderConfirm = () => {
|
const OrderConfirm = () => {
|
||||||
@@ -271,30 +272,31 @@ const OrderConfirm = () => {
|
|||||||
// icon: 'success'
|
// icon: 'success'
|
||||||
// })
|
// })
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('支付失败:', error)
|
return navTo('/user/order/order?statusFilter=0', true)
|
||||||
|
// console.error('支付失败:', error)
|
||||||
|
|
||||||
// 只处理PaymentHandler未处理的错误
|
// 只处理PaymentHandler未处理的错误
|
||||||
if (!error.handled) {
|
// if (!error.handled) {
|
||||||
let errorMessage = '支付失败,请重试';
|
// let errorMessage = '支付失败,请重试';
|
||||||
|
//
|
||||||
// 根据错误类型提供具体提示
|
// // 根据错误类型提供具体提示
|
||||||
if (error.message?.includes('余额不足')) {
|
// if (error.message?.includes('余额不足')) {
|
||||||
errorMessage = '账户余额不足,请充值后重试';
|
// errorMessage = '账户余额不足,请充值后重试';
|
||||||
} else if (error.message?.includes('优惠券')) {
|
// } else if (error.message?.includes('优惠券')) {
|
||||||
errorMessage = '优惠券使用失败,请重新选择';
|
// errorMessage = '优惠券使用失败,请重新选择';
|
||||||
} else if (error.message?.includes('库存')) {
|
// } else if (error.message?.includes('库存')) {
|
||||||
errorMessage = '商品库存不足,请减少购买数量';
|
// errorMessage = '商品库存不足,请减少购买数量';
|
||||||
} else if (error.message?.includes('地址')) {
|
// } else if (error.message?.includes('地址')) {
|
||||||
errorMessage = '收货地址信息有误,请重新选择';
|
// errorMessage = '收货地址信息有误,请重新选择';
|
||||||
} else if (error.message) {
|
// } else if (error.message) {
|
||||||
errorMessage = error.message;
|
// errorMessage = error.message;
|
||||||
}
|
// }
|
||||||
|
// Taro.showToast({
|
||||||
Taro.showToast({
|
// title: errorMessage,
|
||||||
title: errorMessage,
|
// icon: 'error'
|
||||||
icon: 'error'
|
// })
|
||||||
})
|
// console.log('跳去未付款的订单列表页面')
|
||||||
}
|
// }
|
||||||
} finally {
|
} finally {
|
||||||
setPayLoading(false)
|
setPayLoading(false)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -441,7 +441,7 @@ function OrderList(props: OrderListProps) {
|
|||||||
payStatus={item.payStatus}
|
payStatus={item.payStatus}
|
||||||
realTime={false}
|
realTime={false}
|
||||||
showSeconds={false}
|
showSeconds={false}
|
||||||
mode="text"
|
mode={'badge'}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
getOrderStatusText(item)
|
getOrderStatusText(item)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import Taro from '@tarojs/taro'
|
import Taro from '@tarojs/taro'
|
||||||
import { processInviteScene, createInviteRelation } from '@/api/invite'
|
import { createInviteRelation } from '@/api/invite'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 邀请参数接口
|
* 邀请参数接口
|
||||||
|
|||||||
Reference in New Issue
Block a user