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,153 @@
import { View, Text, Input, Textarea } from '@tarojs/components';
import { useState } from 'react';
import Taro from '@tarojs/taro';
import NavBar from '@/components/NavBar';
export default function InvoiceApplyPage() {
const [invoiceType, setInvoiceType] = useState<'personal' | 'company'>('personal');
const [formData, setFormData] = useState({
title: '',
taxNumber: '',
content: '商品明细',
amount: '',
email: '',
remark: ''
});
const handleSubmit = () => {
// TODO: 接入发票申请 API
Taro.showToast({ title: '发票申请功能开发中', icon: 'none' })
};
return (
<View className="bg-gray-100 flex flex-col" style={{ minHeight: '100vh' }}>
<NavBar title="申请发票" />
<View className="flex-1 p-4">
{/* 发票类型 */}
<View className="bg-white rounded-lg p-4 mb-4">
<Text className="text-base font-medium mb-3 block"></Text>
<View className="flex" style={{ gap: '16px' }}>
<View
className={`flex-1 p-3 rounded-lg border-2 text-center ${
invoiceType === 'personal'
? 'border-red-500 bg-red-50'
: 'border-gray-300'
}`}
onClick={() => setInvoiceType('personal')}
>
<Text className={invoiceType === 'personal' ? 'text-red-500' : 'text-gray-600'}>
</Text>
</View>
<View
className={`flex-1 p-3 rounded-lg border-2 text-center ${
invoiceType === 'company'
? 'border-red-500 bg-red-50'
: 'border-gray-300'
}`}
onClick={() => setInvoiceType('company')}
>
<Text className={invoiceType === 'company' ? 'text-red-500' : 'text-gray-600'}>
</Text>
</View>
</View>
</View>
{/* 发票信息 */}
<View className="bg-white rounded-lg p-4 mb-4">
<Text className="text-base font-medium mb-3 block"></Text>
<View className="mb-4">
<Text className="text-sm text-gray-600 mb-2 block"></Text>
<Input
className="w-full p-3 bg-gray-100 rounded-lg text-sm"
placeholder="请输入发票抬头"
value={formData.title}
onInput={(e: any) => setFormData(prev => ({ ...prev, title: e.detail.value }))}
/>
</View>
{invoiceType === 'company' && (
<View className="mb-4">
<Text className="text-sm text-gray-600 mb-2 block"></Text>
<Input
className="w-full p-3 bg-gray-100 rounded-lg text-sm"
placeholder="请输入纳税人识别号"
value={formData.taxNumber}
onInput={(e: any) => setFormData(prev => ({ ...prev, taxNumber: e.detail.value }))}
/>
</View>
)}
<View className="mb-4">
<Text className="text-sm text-gray-600 mb-2 block"></Text>
<View className="flex" style={{ gap: '16px' }}>
<View
className={`px-4 py-2 rounded-lg ${
formData.content === '商品明细' ? 'bg-red-500 text-white' : 'bg-gray-100 text-gray-600'
}`}
onClick={() => setFormData(prev => ({ ...prev, content: '商品明细' }))}
>
<Text></Text>
</View>
<View
className={`px-4 py-2 rounded-lg ${
formData.content === '商品类别' ? 'bg-red-500 text-white' : 'bg-gray-100 text-gray-600'
}`}
onClick={() => setFormData(prev => ({ ...prev, content: '商品类别' }))}
>
<Text></Text>
</View>
</View>
</View>
<View className="mb-4">
<Text className="text-sm text-gray-600 mb-2 block"></Text>
<Input
className="w-full p-3 bg-gray-100 rounded-lg text-sm"
placeholder="请输入发票金额"
type="digit"
value={formData.amount}
onInput={(e: any) => setFormData(prev => ({ ...prev, amount: e.detail.value }))}
/>
</View>
</View>
{/* 接收方式 */}
<View className="bg-white rounded-lg p-4 mb-4">
<Text className="text-base font-medium mb-3 block"></Text>
<View className="mb-4">
<Text className="text-sm text-gray-600 mb-2 block"></Text>
<Input
className="w-full p-3 bg-gray-100 rounded-lg text-sm"
placeholder="请输入接收邮箱"
value={formData.email}
onInput={(e: any) => setFormData(prev => ({ ...prev, email: e.detail.value }))}
/>
</View>
<View className="mb-4">
<Text className="text-sm text-gray-600 mb-2 block"></Text>
<Textarea
className="w-full p-3 bg-gray-100 rounded-lg text-sm"
placeholder="选填,可填写备注信息"
value={formData.remark}
onInput={(e: any) => setFormData(prev => ({ ...prev, remark: e.detail.value }))}
/>
</View>
</View>
</View>
<View className="p-4 bg-white border-t border-gray-200" style={{ paddingBottom: '20px' }}>
<View
className="bg-red-500 text-white rounded-full w-full h-12 flex items-center justify-center"
onClick={handleSubmit}
>
<Text className="text-white font-medium"></Text>
</View>
</View>
</View>
);
}