feat(user): 新增收货地址管理及售后申请页面

- 新增地址类型定义,增强前端地址数据结构
- 新增地址编辑页面,支持地址智能识别和定位选点功能
- 地址编辑支持省市区选择及默认地址设置
- 新增地址列表页面,支持地址展示、删除、编辑和选择功能
- 实现售后申请页面,支持选择售后类型和退款原因
- 售后申请支持商品选择、退款金额计算和凭证上传
- 新增售后详情页面,支持售后状态展示及申请取消
- 优化页面加载和用户交互体验,增加错误提示和权限处理
This commit is contained in:
2026-07-01 12:11:56 +08:00
parent bf6ed504cc
commit 1fa58040f3
636 changed files with 58878 additions and 716 deletions

View File

@@ -0,0 +1,191 @@
import React, { useState } from 'react';
import { View, Text } from '@tarojs/components';
import { Card, Divider, Button } from '@nutui/nutui-react-taro';
import { Scan, Success, Failure, Tips } from '@nutui/icons-react-taro';
import Taro from '@tarojs/taro';
import QRLoginScanner from '@/components/QRLoginScanner';
import { useUser } from '@/hooks/useUser';
/**
* 扫码登录页面
*/
const QRLoginPage: React.FC = () => {
const [loginHistory, setLoginHistory] = useState<any[]>([]);
const { getDisplayName } = useUser();
// 处理扫码成功
const handleScanSuccess = (result: any) => {
// 添加到登录历史
const newRecord = {
id: Date.now(),
time: new Date().toLocaleString(),
userInfo: result.userInfo,
success: true
};
setLoginHistory(prev => [newRecord, ...prev.slice(0, 4)]); // 只保留最近5条记录
// 显示成功提示
Taro.showToast({
title: '登录确认成功',
icon: 'success',
duration: 2000
});
};
// 处理扫码失败
const handleScanError = (error: string) => {
console.error('扫码登录失败:', error);
// 添加到登录历史
const newRecord = {
id: Date.now(),
time: new Date().toLocaleString(),
error,
success: false
};
setLoginHistory(prev => [newRecord, ...prev.slice(0, 4)]);
};
// 返回上一页
// const handleBack = () => {
// Taro.navigateBack();
// };
// 清除历史记录
const clearHistory = () => {
setLoginHistory([]);
Taro.showToast({
title: '已清除历史记录',
icon: 'success'
});
};
return (
<View className='qr-login-page min-h-screen bg-gray-50'>
{/* 导航栏 */}
{/*<NavBar*/}
{/* title="扫码登录"*/}
{/* leftShow*/}
{/* onBackClick={handleBack}*/}
{/* leftText={<ArrowLeft />}*/}
{/* className="bg-white"*/}
{/*/>*/}
{/* 主要内容 */}
<View className='p-4'>
{/* 用户信息卡片 */}
<Card className='bg-white rounded-lg shadow-sm'>
<View className='p-4'>
<View className='flex items-center mb-4'>
<View className='w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-3'>
<Scan className='text-blue-500' size='24' />
</View>
<View>
<Text className='text-lg font-bold text-gray-800'>
{getDisplayName()}
</Text>
<Text className='text-sm text-gray-500'>
使
</Text>
</View>
</View>
{/* 扫码登录组件 */}
<QRLoginScanner
onSuccess={handleScanSuccess}
onError={handleScanError}
buttonText='开始扫码登录'
showStatus
/>
</View>
</Card>
{/* 使用说明 */}
<Card className='bg-white rounded-lg shadow-sm'>
<View className='p-4'>
<View className='flex items-center mb-3'>
<Tips className='text-orange-500 mr-2' />
<Text className='font-medium text-gray-800'>使</Text>
</View>
<View className='text-sm text-gray-600'>
<Text className='block'>1. </Text>
<Text className='block'>2. "扫码登录"</Text>
<Text className='block'>3. 使</Text>
<Text className='block'>4. </Text>
</View>
</View>
</Card>
{/* 登录历史 */}
{loginHistory.length > 0 && (
<Card className='bg-white rounded-lg shadow-sm'>
<View className='p-4'>
<View className='flex items-center justify-between mb-3'>
<Text className='font-medium text-gray-800'></Text>
<Button
size='small'
type='default'
onClick={clearHistory}
className='text-xs'
>
</Button>
</View>
<View>
{loginHistory.map((record, index) => (
<View key={record.id}>
<View className='flex items-center justify-between'>
<View className='flex items-center'>
{record.success ? (
<Success className='text-green-500 mr-2' size='16' />
) : (
<Failure className='text-red-500 mr-2' size='16' />
)}
<View>
<Text className='text-sm text-gray-800'>
{record.success ? '登录成功' : '登录失败'}
</Text>
{record.error && (
<Text className='text-xs text-red-500'>
{record.error}
</Text>
)}
</View>
</View>
<Text className='text-xs text-gray-500'>
{record.time}
</Text>
</View>
{index < loginHistory.length - 1 && (
<Divider className='my-2' />
)}
</View>
))}
</View>
</View>
</Card>
)}
{/* 安全提示 */}
<Card className='bg-yellow-50 border border-yellow-200 rounded-lg'>
<View className='p-4'>
<View className='flex items-start'>
<Tips className='text-yellow-600 mr-2 mt-1' size='16' />
<View>
<Text className='text-sm font-medium text-yellow-800 mb-1'>
</Text>
<Text className='text-xs text-yellow-700'>
</Text>
</View>
</View>
</View>
</Card>
</View>
</View>
);
};
export default QRLoginPage;