feat(invoice): 实现发票申请与管理功能

新增功能:
- 发票管理页面:支持查看发票列表、统计、Tab筛选
- 发票申请流程:支持电子/纸质发票、个人/企业抬头
- 发票状态追踪:待处理、处理中、已完成、已取消
- 发票抬头模板:支持保存和复用常用抬头
- 发票下载:已完成的电子发票可下载

组件架构:
- InvoiceCard: 发票卡片展示(React.memo优化)
- InvoiceApplyForm: 开票申请表单
- InvoiceApplyModal: 申请弹窗
- InvoiceStatusBadge: 状态徽章
- InvoiceTitleSelector: 抬头选择器
- InvoiceTypeSelector: 发票类型选择

入口集成:
- 设置页添加"账单与发票"Tab
- Billing页面添加发票管理入口
- 订阅支付成功后提示开票

Mock数据:
- 多用户发票数据(不同状态)
- 可开票订单
- 抬头模板

性能优化:
- InvoiceCard 使用 React.memo 避免不必要重渲染
- useColorModeValue 移到组件顶层调用
- loadInvoices/loadStats 使用 useCallback

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zdl
2025-12-26 12:49:51 +08:00
parent 3072a9a0b7
commit c44389f4fe
18 changed files with 3037 additions and 139 deletions

View File

@@ -31,8 +31,9 @@ import {
PinInput,
PinInputField
} from '@chakra-ui/react';
import { Link2, Trash2, Pencil, Smartphone, Mail } from 'lucide-react';
import { Link2, Trash2, Pencil, Smartphone, Mail, FileText, CreditCard } from 'lucide-react';
import { WechatOutlined } from '@ant-design/icons';
import { useNavigate } from 'react-router-dom';
import { useAuth } from '../../contexts/AuthContext';
import { getApiBase } from '../../utils/apiConfig';
import { logger } from '../../utils/logger';
@@ -41,6 +42,7 @@ import { useProfileEvents } from '../../hooks/useProfileEvents';
export default function SettingsPage() {
const { user, updateUser } = useAuth();
const toast = useToast();
const navigate = useNavigate();
// 深色模式固定颜色Settings 页面始终使用深色主题)
const headingColor = 'white';
@@ -222,6 +224,7 @@ export default function SettingsPage() {
<Tabs variant="enclosed" colorScheme="blue">
<TabList>
<Tab color={textColor} _selected={{ color: 'blue.500', borderColor: 'blue.500' }}>账户绑定</Tab>
<Tab color={textColor} _selected={{ color: 'blue.500', borderColor: 'blue.500' }}>账单与发票</Tab>
</TabList>
<TabPanels>
@@ -403,6 +406,71 @@ export default function SettingsPage() {
</VStack>
</TabPanel>
{/* 账单与发票 */}
<TabPanel>
<VStack spacing={6} align="stretch">
{/* 订阅管理 */}
<Card bg={cardBg} borderColor={borderColor}>
<CardHeader>
<Heading size="md" color={headingColor}>订阅管理</Heading>
</CardHeader>
<CardBody>
<HStack justify="space-between">
<VStack align="start" spacing={1}>
<HStack>
<CreditCard size={20} />
<Text fontWeight="medium" color={textColor}>
{user?.subscription_type === 'max' ? 'Max 会员' :
user?.subscription_type === 'pro' ? 'Pro 会员' : '免费版'}
</Text>
{user?.subscription_type && user?.subscription_type !== 'free' && (
<Badge colorScheme="purple" size="sm">有效</Badge>
)}
</HStack>
<Text fontSize="sm" color={subTextColor}>
管理您的会员订阅和续费
</Text>
</VStack>
<Button
colorScheme="purple"
onClick={() => navigate('/home/pages/account/subscription')}
>
管理订阅
</Button>
</HStack>
</CardBody>
</Card>
{/* 发票管理 */}
<Card bg={cardBg} borderColor={borderColor}>
<CardHeader>
<Heading size="md" color={headingColor}>发票管理</Heading>
</CardHeader>
<CardBody>
<HStack justify="space-between">
<VStack align="start" spacing={1}>
<HStack>
<FileText size={20} />
<Text fontWeight="medium" color={textColor}>
电子发票申请与下载
</Text>
</HStack>
<Text fontSize="sm" color={subTextColor}>
已支付的订单可申请开具电子发票
</Text>
</VStack>
<Button
colorScheme="teal"
onClick={() => navigate('/home/pages/account/invoice')}
>
管理发票
</Button>
</HStack>
</CardBody>
</Card>
</VStack>
</TabPanel>
</TabPanels>
</Tabs>
</VStack>