feat(user): 新增收货地址管理及售后申请页面
- 新增地址类型定义,增强前端地址数据结构 - 新增地址编辑页面,支持地址智能识别和定位选点功能 - 地址编辑支持省市区选择及默认地址设置 - 新增地址列表页面,支持地址展示、删除、编辑和选择功能 - 实现售后申请页面,支持选择售后类型和退款原因 - 售后申请支持商品选择、退款金额计算和凭证上传 - 新增售后详情页面,支持售后状态展示及申请取消 - 优化页面加载和用户交互体验,增加错误提示和权限处理
This commit is contained in:
178
src_bak/pages/user/benefit-exchange-confirm/index.tsx
Normal file
178
src_bak/pages/user/benefit-exchange-confirm/index.tsx
Normal file
@@ -0,0 +1,178 @@
|
||||
import { View, Text, Image } from '@tarojs/components';
|
||||
import Taro, { useRouter } from '@tarojs/taro';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { getBenefitPackageDetail, exchangeBenefitPackage } from '@/api/shop/shopMemberBenefit';
|
||||
import { getDefaultAddress } from '@/api/shop/shopUserAddress';
|
||||
import { getUserBalance } from '@/api/system/user/balance';
|
||||
import './index.scss';
|
||||
|
||||
definePageConfig({
|
||||
navigationBarTitleText: '确认兑换',
|
||||
});
|
||||
|
||||
export default function BenefitExchangeConfirmPage() {
|
||||
const router = useRouter();
|
||||
const pkgId = Number(router.params.id);
|
||||
|
||||
const [pkg, setPkg] = useState<any>(null);
|
||||
const [address, setAddress] = useState<any>(null);
|
||||
const [userBalance, setUserBalance] = useState<string>('--');
|
||||
const [userPoints, setUserPoints] = useState<string>('--');
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
loadPackage();
|
||||
loadAddress();
|
||||
loadUserBalance();
|
||||
}, []);
|
||||
|
||||
const loadPackage = async () => {
|
||||
const res = await getBenefitPackageDetail(pkgId);
|
||||
if (res.code === 200) setPkg(res.data);
|
||||
};
|
||||
|
||||
const loadAddress = async () => {
|
||||
const res = await getDefaultAddress();
|
||||
if (res.code === 200 && res.data) setAddress(res.data);
|
||||
};
|
||||
|
||||
const loadUserBalance = async () => {
|
||||
try {
|
||||
const data = await getUserBalance();
|
||||
setUserBalance(data.balance || '0');
|
||||
setUserPoints(String(data.points || 0));
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelectAddress = () => {
|
||||
Taro.navigateTo({ url: '/pages/user/address-list?select=1' });
|
||||
};
|
||||
|
||||
const handleExchange = async () => {
|
||||
if (!pkg) return;
|
||||
|
||||
if (pkg.needShip && !address) {
|
||||
Taro.showToast({ title: '请先选择收货地址', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
|
||||
Taro.showModal({
|
||||
title: '确认兑换',
|
||||
content: `确认兑换「${pkg.name}」?`,
|
||||
success: async (res) => {
|
||||
if (!res.confirm) return;
|
||||
setSubmitting(true);
|
||||
try {
|
||||
const res2 = await exchangeBenefitPackage({
|
||||
packageId: pkgId,
|
||||
addressId: address?.id,
|
||||
});
|
||||
if (res2.code === 200) {
|
||||
Taro.showToast({ title: '兑换申请成功', icon: 'success' });
|
||||
setTimeout(() => {
|
||||
Taro.redirectTo({ url: '/pages/user/benefit-exchange-list/index' });
|
||||
}, 1500);
|
||||
} else {
|
||||
Taro.showToast({ title: res2.message || '兑换失败', icon: 'none' });
|
||||
}
|
||||
} catch (e) {
|
||||
Taro.showToast({ title: '网络错误', icon: 'none' });
|
||||
} finally {
|
||||
setSubmitting(false);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
if (!pkg) return null;
|
||||
|
||||
return (
|
||||
<View className="confirm-page">
|
||||
{/* 收货地址 */}
|
||||
{pkg.needShip === 1 && (
|
||||
<View className="address-card" onClick={handleSelectAddress}>
|
||||
{address ? (
|
||||
<>
|
||||
<View className="addr-info">
|
||||
<Text className="addr-name">{address.name}</Text>
|
||||
<Text className="addr-phone">{address.phone}</Text>
|
||||
</View>
|
||||
<Text className="addr-detail">
|
||||
{address.province}{address.city}{address.district}{address.detail}
|
||||
</Text>
|
||||
</>
|
||||
) : (
|
||||
<Text className="addr-empty">+ 请选择收货地址</Text>
|
||||
)}
|
||||
<Text className="addr-arrow">></Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* 权益包信息 */}
|
||||
<View className="pkg-info-card">
|
||||
{pkg.coverImage && (
|
||||
<Image className="pkg-img" src={pkg.coverImage} mode="aspectFill" />
|
||||
)}
|
||||
<View className="pkg-detail">
|
||||
<Text className="pkg-name">{pkg.name}</Text>
|
||||
{pkg.description && (
|
||||
<Text className="pkg-desc">{pkg.description}</Text>
|
||||
)}
|
||||
<View className="pkg-cost-row">
|
||||
{pkg.pointsCost > 0 && (
|
||||
<Text className="cost-item points">{pkg.pointsCost} 积分</Text>
|
||||
)}
|
||||
{pkg.balanceCost > 0 && (
|
||||
<Text className="cost-item balance">¥{pkg.balanceCost}</Text>
|
||||
)}
|
||||
{!pkg.pointsCost && !pkg.balanceCost && (
|
||||
<Text className="cost-item free">免费兑换</Text>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 我的资产 */}
|
||||
<View className="assets-card">
|
||||
<Text className="assets-title">我的资产</Text>
|
||||
<View className="assets-row">
|
||||
{pkg.pointsCost > 0 && (
|
||||
<View className="asset-item">
|
||||
<Text className="asset-value">{userPoints}</Text>
|
||||
<Text className="asset-label">当前积分</Text>
|
||||
</View>
|
||||
)}
|
||||
{pkg.balanceCost > 0 && (
|
||||
<View className="asset-item">
|
||||
<Text className="asset-value">{userBalance}</Text>
|
||||
<Text className="asset-label">当前余额</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 须知 */}
|
||||
<View className="notice-card">
|
||||
<Text className="notice-title">兑换须知</Text>
|
||||
<Text className="notice-item">· 兑换后平台将安排配送,请耐心等待</Text>
|
||||
<Text className="notice-item">· 仅待处理状态可申请取消</Text>
|
||||
<Text className="notice-item">· 如有问题请联系客服</Text>
|
||||
{pkg.validDays && (
|
||||
<Text className="notice-item">· 权益有效期:{pkg.validDays}天</Text>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* 底部按钮 */}
|
||||
<View className="bottom-bar">
|
||||
<View
|
||||
className={`confirm-btn ${submitting ? 'disabled' : ''}`}
|
||||
onClick={!submitting ? handleExchange : undefined}
|
||||
>
|
||||
{submitting ? '提交中...' : '确认兑换'}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user