import React, { useEffect, useState, useCallback, useRef } from 'react';
import { Layout, Avatar, Dropdown, Space, Modal, Form, Input, message, notification, Tag, Button, Typography, Radio, Drawer, Tabs, Progress, Collapse, ConfigProvider } from 'antd';
import { QRCodeSVG } from 'qrcode.react';
import {
  PlayCircleOutlined,
  WalletOutlined,
  LogoutOutlined,
  UserOutlined,
  ThunderboltOutlined,
  HomeOutlined,
  DashboardOutlined,
  CodeOutlined,
  LockOutlined,
  PlusOutlined,
  GiftOutlined,
  BellOutlined,
  SettingOutlined,
  AppstoreOutlined,
  FileTextOutlined,
  StarOutlined,
  HeartOutlined,
  CameraOutlined,
  CloudOutlined,
  SmileOutlined,
  TrophyOutlined,
  RocketOutlined,
  BulbOutlined,
  PictureOutlined,
  VideoCameraOutlined,
  AudioOutlined,
  MailOutlined,
  PhoneOutlined,
  GlobalOutlined,
  TeamOutlined,
  BarChartOutlined,
  PieChartOutlined,
  LineChartOutlined,
  SecurityScanOutlined,
  ApiOutlined,
  DatabaseOutlined,
  CloudServerOutlined,
  MessageOutlined,
  MenuOutlined,
  RobotOutlined,
  ProfileOutlined,
  CloseOutlined,
  CrownOutlined,
  CrownFilled,
  FireOutlined,
  BankFilled,
  CheckCircleFilled,
  WechatOutlined,
  AlipayCircleOutlined,
  ShoppingCartOutlined,
  DownOutlined,
  UpOutlined,
  RightOutlined,
  StarFilled,
  FireFilled,
} from '@ant-design/icons';
import { Outlet, useNavigate, useLocation } from 'react-router-dom';
import { useAuthStore } from '../../store/useAuthStore';
import { getMenuConfigs, getCreditProductCatalog, getPaymentMethods, createRechargeOrder, getPaymentOrder, cancelPaymentOrder, getSiteInfo, getUnreadCount, createContactRequest, getUser, changePassword, changeUsername } from '../../api';
import type { CreditProduct, CreditProductCatalog } from '../../types';
import NotificationPopup from '../NotificationPopup';
import ActivityBanner from './ActivityBanner';
import './AppLayout.css';


// ── ResourceCapacity 类型（与 src/types/index.ts 保持一致） ──
type ResourceCapacityData = {
  enabled: boolean;
  usedBytes: number;
  totalBytes: number;
  availableBytes: number;
  usagePercent: number;
  exceeded: boolean;
  limitValue: string;
  limitUnit: string;
};

/**
 * 资源存储展示卡片
 * - enabled === true：显示「已用 / 总额」+ 进度条（超额时变红并提示）
 * - enabled === false：按 usedBytes 大小自动选 KB / MB / GB / TB 单位显示「当前使用」
 */
const StorageCard: React.FC<{ data: ResourceCapacityData | null }> = ({ data }) => {
  if (!data) return null;

  // 单位：后端返回的 limitUnit（KB / MB / GB）
  const unit = (data.limitUnit || 'GB').toUpperCase();
  const divisor = unit === 'GB' ? 1024 ** 3 : unit === 'MB' ? 1024 ** 2 : 1024;

  // 百分比（可能 > 100）
  const rawPercent = Number(data.usagePercent) || 0;
  // 进度条宽度最多 100%
  const barPercent = Math.min(100, Math.max(0, rawPercent));

  // 总额：优先用后端 limitValue，兜底 totalBytes / divisor
  const total = data.limitValue
    ? parseFloat(data.limitValue)
    : data.totalBytes / divisor;

  // 已用 = 总额 × 百分比 / 100（保证数字与 percent 自洽）
  const used = (total * rawPercent) / 100;

  // 超额判断
  const isOver = data.exceeded || rawPercent >= 100;

  // enabled === false 时按 usedBytes 自动选单位
  const KB = 1024;
  const MB = 1024 ** 2;
  const GB = 1024 ** 3;
  const TB = 1024 ** 4;
  const formatUsedAuto = (bytes: number) => {
    const b = Number(bytes) || 0;
    if (b >= TB) return { val: (b / TB).toFixed(2), unit: 'TB' };
    if (b >= GB) return { val: (b / GB).toFixed(2), unit: 'GB' };
    if (b >= MB) return { val: (b / MB).toFixed(2), unit: 'MB' };
    return { val: (b / KB).toFixed(2), unit: 'KB' };
  };
  const usedAuto = formatUsedAuto(data.usedBytes);

  return (
    <div
      style={{
        // marginTop: 12,
        marginBottom: 12,
        padding: '0 12px',
        paddingTop: 6,
        borderRadius: 10,
        background: 'linear-gradient(135deg, rgba(248, 250, 252, 0.9) 0%, rgba(241, 245, 249, 0.9) 100%)',
        // border: `1px solid ${isOver ? 'rgba(239, 68, 68, 0.25)' : 'rgba(99, 102, 241, 0.15)'}`,
        boxShadow: '0 2px 12px rgba(0, 0, 0, 0.04)',
      }}
    >
      <div
        style={{
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'space-between',
          marginBottom: 6,
          fontSize: 12,
          color: '#475569',
        }}
      >
        {/* <span style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
          <DatabaseOutlined style={{ fontSize: 12, color: isOver ? '#ef4444' : '#6366f1' }} />
          {rawPercent.toFixed(1)}%
        </span> */}
        {data.enabled ? (
          <></>
        ) : (

          <span style={{ fontWeight: 500, color: '#1e293b' }}>
            <DatabaseOutlined style={{ fontSize: 12, color: isOver ? '#ef4444' : '#6366f1', marginRight: 4 }} />

            当前使用 {usedAuto.val} {usedAuto.unit}
          </span>
        )}
      </div>
      {data.enabled && (
        <>

          <div
            style={{
              marginTop: 4,
              display: 'flex',
              justifyContent: 'space-between',
              fontSize: 11,
              color: isOver ? '#ef4444' : '#94a3b8',
            }}
          >
            <div style={{
              height: '100%',
              width: '100%',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'space-between',
              marginBottom: 6,
              fontSize: 12,
              color: isOver ? '#000000ff' : '#000000ff',
              padding: '0 8px',

            }}>
              <span style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
                <DatabaseOutlined style={{ fontSize: 12, color: isOver ? '#000000ff' : '#000000ff' }} />
                {rawPercent.toFixed(1)}%
              </span>
              {data.enabled ? (
                <span style={{ fontWeight: 500, color: isOver ? '#000000ff' : '#000000ff' }}>
                  {used.toFixed(2)} / {total.toFixed(2)} {unit}
                </span>
              ) : (
                <span style={{ fontWeight: 500, color: '#1e293b' }}>
                  当前使用 {usedAuto.val} {usedAuto.unit}
                </span>
              )}

            </div>
            {/* <span>
              {isOver
                ? `存储超额 · 超用 ${Math.abs(available).toFixed(2)} ${unit}`
                : `剩余 ${available.toFixed(2)} ${unit}`}
            </span> */}
            {/* <span>{rawPercent.toFixed(1)}%</span> */}

          </div>
          <div
            style={{
              width: '100%',
              height: 6,
              background: '#e2e8f0',
              borderRadius: 50,
              overflow: 'hidden',
              position: 'relative',

            }}
          >


            <div
              style={{
                width: `${barPercent}%`,
                height: '100%',

                background: rawPercent < 50
                  ? 'linear-gradient(90deg, #279951, #b7fad0)'
                  : rawPercent < 85
                    ? 'linear-gradient(90deg, #ffd759, #fff6d4)'
                    : 'linear-gradient(90deg, #ef4444, #dc2626)',
                borderRadius: 2,
                transition: 'width 0.4s ease',
              }}
            />

          </div>
        </>
      )}
    </div>
  );
};

interface MenuConfig {
  id: string;
  key?: string;
  label: string;
  path: string;
  icon: string;
  sortOrder: number;
  isActive: boolean;
  parentId?: string | null;
  parent_id?: string | null;
  menuType?: string;
  menu_type?: string;
}

const iconMap: Record<string, React.ReactNode> = {
  HomeOutlined: <HomeOutlined />,
  DashboardOutlined: <DashboardOutlined />,
  CodeOutlined: <CodeOutlined />,
  PlayCircleOutlined: <PlayCircleOutlined />,
  WalletOutlined: <WalletOutlined />,
  SettingOutlined: <SettingOutlined />,
  BellOutlined: <BellOutlined />,
  UserOutlined: <UserOutlined />,
  AppstoreOutlined: <AppstoreOutlined />,
  FileTextOutlined: <FileTextOutlined />,
  StarOutlined: <StarOutlined />,
  HeartOutlined: <HeartOutlined />,
  CameraOutlined: <CameraOutlined />,
  RobotOutlined: <RobotOutlined />,
  GiftOutlined: <GiftOutlined />,
  ThunderboltOutlined: <ThunderboltOutlined />,
  CloudOutlined: <CloudOutlined />,
  SmileOutlined: <SmileOutlined />,
  TrophyOutlined: <TrophyOutlined />,
  RocketOutlined: <RocketOutlined />,
  BulbOutlined: <BulbOutlined />,
  PictureOutlined: <PictureOutlined />,
  VideoCameraOutlined: <VideoCameraOutlined />,
  AudioOutlined: <AudioOutlined />,
  MailOutlined: <MailOutlined />,
  PhoneOutlined: <PhoneOutlined />,
  GlobalOutlined: <GlobalOutlined />,
  TeamOutlined: <TeamOutlined />,
  BarChartOutlined: <BarChartOutlined />,
  PieChartOutlined: <PieChartOutlined />,
  LineChartOutlined: <LineChartOutlined />,
  SecurityScanOutlined: <SecurityScanOutlined />,
  ApiOutlined: <ApiOutlined />,
  DatabaseOutlined: <DatabaseOutlined />,
  CloudServerOutlined: <CloudServerOutlined />,
};

const SIDEBAR_W = 240;

const GRADIENTS = [
  { gradient: 'linear-gradient(135deg, #c9a96e, #a67c52)', shadow: 'rgba(201,169,110,0.25)', icon: <StarFilled /> },
  { gradient: 'linear-gradient(135deg, #4a5568, #2d3748)', shadow: 'rgba(74,85,104,0.25)', icon: <FireFilled /> },
  { gradient: 'linear-gradient(135deg, #718096, #4a5568)', shadow: 'rgba(113,128,150,0.25)', icon: <CrownFilled /> },
  { gradient: 'linear-gradient(135deg, #5a67d8, #434190)', shadow: 'rgba(90,103,216,0.25)', icon: <BankFilled /> },
];

const MEMBERSHIP_GRADIENTS = [
  { gradient: 'linear-gradient(135deg, #f6ad55, #dd6b20)', shadow: 'rgba(246,173,85,0.25)', icon: <CrownOutlined /> },
  { gradient: 'linear-gradient(135deg, #667eea, #5a67d8)', shadow: 'rgba(102,126,234,0.25)', icon: <CrownOutlined /> },
  { gradient: 'linear-gradient(135deg, #94a3b8, #64748b)', shadow: 'rgba(148,163,184,0.25)', icon: <StarFilled /> },
  { gradient: 'linear-gradient(135deg, #c9a96e, #a67c52)', shadow: 'rgba(201,169,110,0.25)', icon: <StarFilled /> },
  { gradient: 'linear-gradient(135deg, #718096, #4a5568)', shadow: 'rgba(113,128,150,0.25)', icon: <CrownOutlined /> },
  { gradient: 'linear-gradient(135deg, #5a67d8, #434190)', shadow: 'rgba(90,103,216,0.25)', icon: <BankFilled /> },
];

const FAQ_ITEMS = [
  {
    key: 'points-validity',
    label: '积分有效期规则',
    children: (
      <div style={{ color: '#64748b', lineHeight: 1.8, fontSize: 13 }}>
        <p style={{ margin: '0 0 8px' }}>1、会员积分：月卡与年卡的积分配额均按月发放，自到账起 31 天内有效，到期自动重置（上周期未使用积分清零 + 下发下周期度积分）；</p>
        <p style={{ margin: '0 0 8px' }}>2、充值通用积分：自到账起 2 年内有效，到期清零，不退不换；</p>
        <p style={{ margin: '0 0 8px' }}>3、模型专属积分有效期升级：2026年8月7日（含）起购买，有效期为2年；此前购买，有效期为6个月。有效期自积分到账之日起计算，到期清零，不退不换；</p>
        <p style={{ margin: 0 }}>4、每日登录积分：赠送 20 积分，仅限当日使用，次日自动清零。</p>
      </div>
    ),
  },
  {
    key: 'refund-rules',
    label: '会员&积分 退款规则',
    children: (
      <div style={{ color: '#64748b', lineHeight: 1.8, fontSize: 13 }}>
        <p style={{ margin: 0 }}>会员与积分属于虚拟数字商品，开通后权益即时生效，因此一经购买不支持任何理由的退款或转让。建议您在支付前确认所选内容，如遇重复扣款或系统异常，请联系客服，我们会尽快为您处理。感谢理解 💛</p>
      </div>
    ),
  },
  {
    key: 'points-return',
    label: '积分返还规则',
    children: (
      <div style={{ color: '#64748b', lineHeight: 1.8, fontSize: 13 }}>
        <p style={{ margin: 0 }}>若生成分成失败，被扣的对应积分将在 2 小时内返还至原账户，在「积分明细页」原消耗记录条目中会展示"任务生成失败，积分已返还"提示。因个别原因导致延迟或未返还的情况，可联系平台客服进行处理。</p>
      </div>
    ),
  },
  {
    key: 'points-consumption',
    label: '积分消耗顺序',
    children: (
      <div style={{ color: '#64748b', lineHeight: 1.8, fontSize: 13 }}>
        <p style={{ margin: '0 0 8px', color: '#475569', fontWeight: 500 }}>积分消耗顺序规则：分为平台默认顺序、用户自定义顺序。</p>
        <p style={{ margin: '0 0 8px' }}>1、平台默认消耗顺序：免费积分 ＞ 模型专享积分 ＞ 订阅会员积分 ＞ 通用充值类积分；</p>
        <p style={{ margin: '0 0 8px', paddingLeft: 12 }}>其中，免费积分包含 赠送的TV专属积分、赠送的指定模型专享积分、每日登录奖励积分等。若同一类型中的积分包含多个细分子类型，子类型之间的消耗顺序按到期时间，优先消耗早到期的；</p>
        <p style={{ margin: '0 0 8px' }}>2、自定义积分消耗顺序：用户可在「个人中心-充值入口」、「模型购买页面」、「积分明细页」自主设置积分的消耗顺序。</p>
        <p style={{ margin: 0, color: '#ef4444' }}>特别注意：模型赠送的限时免费生成次数，会优先于积分被最先使用。</p>
      </div>
    ),
  },
  {
    key: 'get-more-points',
    label: '如何获取更多积分',
    children: (
      <div style={{ color: '#64748b', lineHeight: 1.8, fontSize: 13 }}>
        <p style={{ margin: '0 0 8px' }}>若当前积分不足，可通过以下方式补充：</p>
        <p style={{ margin: '0 0 4px' }}>- 升级会员：购买后立即生效，积分即时到账；</p>
        <p style={{ margin: '0 0 4px' }}>- 单独充值通用积分：按需购买，灵活补充；</p>
        <p style={{ margin: 0 }}>- 单独充值模型专享积分：随用随充，性价比高，适用于对特定模型重度使用的用户。</p>
      </div>
    ),
  },
  {
    key: 'installment',
    label: '关于分期支付',
    children: (
      <div style={{ color: '#64748b', lineHeight: 1.8, fontSize: 13 }}>
        <p style={{ margin: 0 }}>部分商品支持花呗分期，目前分期产生的利息由平台承担，用户限时享受0利息。使用分期支付的商品不支持退款，如有逾期还款或产生退费，平台将收取相应费用。</p>
      </div>
    ),
  },
  {
    key: 'invoice',
    label: '发票申请与联系方式',
    children: (
      <div style={{ color: '#64748b', lineHeight: 1.8, fontSize: 13 }}>
        <p style={{ margin: 0 }}>发票可在「订阅与开票」→「购买记录」中自助申请。如需企业合作，请联系 bd@liblib.ai；其他问题欢迎前往"帮助中心"查询。</p>
      </div>
    ),
  },
  {
    key: 'price-protection',
    label: '会员权益7天保护计划',
    children: (
      <div style={{ color: '#64748b', lineHeight: 1.8, fontSize: 13 }}>
        <p style={{ margin: '0 0 8px' }}>7天内购买的会员，若遇同档位会员有新活动，且赠品力度更高，可申请按差额补发赠品。</p>
        <p style={{ margin: '0 0 4px' }}>1、保护范围：指定模型的免费生成次数、专享积分赠送（会员）。</p>
        <p style={{ margin: '0 0 4px' }}>2、保护条件：支付成功 ≤7 天，且会员仍在有效期内，仅限同档位、同周期、同类型赠品。每笔订单针对同一模型赠品，仅限申请 1 次；</p>
        <p style={{ margin: '0 0 4px' }}>3、权益有效期：补发的权益与原会员同效期，到期未自动清零，不可退款、转让。</p>
        <p style={{ margin: '0 0 4px' }}>4、不参与保护范围：会员订单价格本身(即不退会员差价)；已下线/已结束的活动；通过平台赠送、邀请奖励等非现金方式开通的会员；</p>
        <p style={{ margin: 0 }}>5、特别注意：如未在保护有效期内主动领取保护权益，过期将不会补发；Happy Horse 1.0模型不参与保护。</p>
      </div>
    ),
  },
  {
    key: 'free-points',
    label: '免积分畅享卡 优惠活动如何执行的？',
    children: (
      <div style={{ color: '#64748b', lineHeight: 1.8, fontSize: 13 }}>
        <p style={{ margin: '0 0 8px' }}>免积分权益可让您在权益有效期内，使用对应模型生成不消耗积分，同一模型同时最多运行 1 个免积分任务，高峰期生成可能排队，排队时间受到使用人数、高峰时段、模型后台资源情况、用户当日已生成数量等多种因素有关。</p>
        <p style={{ margin: '0 0 4px', color: '#475569', fontWeight: 500 }}>具体规则如下：</p>
        <p style={{ margin: '0 0 4px' }}>- 独立于订阅周期：免限权益按固定期限计算，与订阅周期无关。无论订阅自动续费、取消还是重新开通，都不会重置或延长该权益的有效期。</p>
        <p style={{ margin: '0 0 4px' }}>- 有效期内升级套餐：如果您在免积分权益仍然有效期内升级套餐，将立即解锁更高等级套餐对应的模型能力，并刷新您的有效期。</p>
        <p style={{ margin: 0 }}>- 合理使用与系统保护：免积分权益仅支持真人手动操作，暂不支持 CLI 和其他自动化脚本等生成。为了保障 GPU 集群稳定运行，如检测到自动化脚本、机器人操作或非真人高频使用行为，系统可能会暂时暂停您的权限进行审核。确认是真人创作者后，将恢复访问权限。</p>
      </div>
    ),
  },
];

const AppLayout: React.FC = () => {
  const navigate = useNavigate();
  const location = useLocation();
  const { user, logout, refreshUser } = useAuthStore();
  const [pwdModalOpen, setPwdModalOpen] = useState(false);
  const [contactModalOpen, setContactModalOpen] = useState(false);
  const [rechargeModalOpen, setRechargeModalOpen] = useState(false);
  const [pwdForm] = Form.useForm();
  const [usernameForm] = Form.useForm();
  const [selectedPlan, setSelectedPlan] = useState<string | null>(null);
  const [menuItems, setMenuItems] = useState<MenuConfig[]>([]);
  const [rechargeOptions, setRechargeOptions] = useState<CreditProduct[]>([]);
  const [subscriptionProducts, setSubscriptionProducts] = useState<CreditProduct[]>([]);
  const [currentSubscription, setCurrentSubscription] = useState<CreditProductCatalog['currentSubscription']>(null);
  const loadCreditCatalog = useCallback(async () => {
    try {
      const data = await getCreditProductCatalog();
      setSubscriptionProducts((data.subscriptionProducts || []).filter((product) => product.isActive));
      setRechargeOptions((data.creditAddons || []).filter((product) => product.isActive));
      setCurrentSubscription(data.currentSubscription || null);
    } catch {
      setSubscriptionProducts([]);
      setRechargeOptions([]);
      setCurrentSubscription(null);
    }
  }, []);
  const [creditsModalOpen, setCreditsModalOpen] = useState(false);
  const [selectedPeriod, setSelectedPeriod] = useState<'monthly' | 'quarterly' | 'yearly'>('monthly');
  const [qrCodeModalOpen, setQrCodeModalOpen] = useState(false);
  const [paymentMethod, setPaymentMethod] = useState<string>('alipay');
  const [paying, setPaying] = useState(false);
  const [countdown, setCountdown] = useState(180);
  const pollingTimerRef = useRef<ReturnType<typeof setInterval> | null>(null);
  const countdownTimerRef = useRef<ReturnType<typeof setInterval> | null>(null);
  const currentOrderNoRef = useRef<string | null>(null);
  const [enabledMethods, setEnabledMethods] = useState<{ alipay: boolean; wechat: boolean }>({ alipay: false, wechat: false });
  const [currentPaymentInfo, setCurrentPaymentInfo] = useState<{
    price: number;
    credits: number;
    qrCode: string;
    method: string;
    title: string;
    originalPrice?: number;
    discountAmount?: number;
    tierName?: string;
    periodLabel?: string;
    isSubscription?: boolean;
  } | null>(null);

  const PENDING_ORDER_KEY = 'pending_payment_order';
  const [unreadCount, setUnreadCount] = useState(0);
  const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
  const [contactHovered, setContactHovered] = useState(false);
  const [contactForm] = Form.useForm();
  const [submittingContact, setSubmittingContact] = useState(false);
  const [contactPosition, setContactPosition] = useState<{ x: number; y: number }>(() => ({
    x: 24,
    y: window.innerHeight * 0.75
  }));
  const [isDragging, setIsDragging] = useState(false);
  const hasMovedRef = useRef(false);
  const dragStartRef = useRef({ x: 0, y: 0 });
  const [mobileExpandedMenus, setMobileExpandedMenus] = useState<Record<string, boolean>>({});
  const [siteName, setSiteName] = useState(() => {
    const cached = localStorage.getItem('siteInfo');
    const name = cached ? JSON.parse(cached).siteName || '' : '';
    if (name) document.title = name;
    return name;
  });
  const [siteLogo, setSiteLogo] = useState(() => {
    const cached = localStorage.getItem('siteInfo');
    const logo = cached ? JSON.parse(cached).siteLogo || '' : '';
    if (logo) {
      let faviconLink = document.querySelector('link[rel="icon"]') as HTMLLinkElement;
      if (!faviconLink) {
        faviconLink = document.createElement('link');
        faviconLink.rel = 'icon';
        document.head.appendChild(faviconLink);
      }
      faviconLink.href = logo;
      faviconLink.type = 'image/png';
    }
    return logo;
  });
  const [siteInfoLoading, setSiteInfoLoading] = useState(!localStorage.getItem('siteInfo'));
  const [bannerVisible, setBannerVisible] = useState(false);

  // 资源存储容量（从 getUser().resource_capacity 获取）
  const [resourceCapacity, setResourceCapacity] = useState<{
    enabled: boolean;
    usedBytes: number;
    totalBytes: number;
    availableBytes: number;
    usagePercent: number;
    exceeded: boolean;
    limitValue: string;
    limitUnit: string;
  } | null>(null);
  const [isMobile, setIsMobile] = useState(false);
  const [operationManualUrl, setOperationManualUrl] = useState('');

  // 监听"被踢出"事件 — 单设备登录互斥，显示顶部通知
  useEffect(() => {
    const handleKickedOut = () => {
      notification.warning({
        message: '登录提示',
        description: '您的账号已在其他设备登录，请重新登录',
        placement: 'top',
        duration: 0, // 不自动关闭
        btn: (
          <Button
            type="primary"
            size="small"
            onClick={() => {
              localStorage.removeItem('token');
              navigate('/login');
            }}
          >
            重新登录
          </Button>
        ),
      });
    };
    window.addEventListener('kicked-out', handleKickedOut);
    return () => window.removeEventListener('kicked-out', handleKickedOut);
  }, [navigate]);

  useEffect(() => {
    getSiteInfo().then(info => {
      const name = info.siteName || '智创';
      const logo = info.siteLogo || '';

      if (name !== siteName) {
        setSiteName(name);
        document.title = name;
      }

      if (logo && logo !== siteLogo) {
        setSiteLogo(logo);
        let faviconLink = document.querySelector('link[rel="icon"]') as HTMLLinkElement;
        if (!faviconLink) {
          faviconLink = document.createElement('link');
          faviconLink.rel = 'icon';
          document.head.appendChild(faviconLink);
        }
        // 相对路径拼接 API 基础地址，确保 favicon 正确加载
        const base = import.meta.env.VITE_API_BASE || '';
        const fullUrl = logo.startsWith('http') || logo.startsWith('data:') ? logo : `${base}${logo.startsWith('/') ? '' : '/'}${logo}`;
        faviconLink.href = fullUrl;
        faviconLink.type = 'image/png';
      }

      if (info.operationManual) {
        setOperationManualUrl(info.operationManual);
      }


      localStorage.setItem('siteInfo', JSON.stringify({ siteName: name, siteLogo: logo }));
    }).catch(() => {
    });

    getUser().then((res: any) => {
      // console.log('[Storage] getUser 返回:', res);

      const rc = res?.resourceCapacity;
      if (rc) {
        setResourceCapacity({
          enabled: !!rc.enabled,
          usedBytes: Number(rc.usedBytes) || 0,
          totalBytes: Number(rc.totalBytes) || 0,
          availableBytes: Number(rc.availableBytes) || 0,
          usagePercent: Number(rc.usagePercent) || 0,
          exceeded: !!rc.exceeded,
          limitValue: rc.limitValue ?? '',
          limitUnit: rc.limitUnit || 'GB',
        });
      }
      // 没数据时不显示
    }).catch(() => {
      // console.error('[Storage] getUser 失败:', err);
      // 接口失败也不显示
    });


  }, []);

  useEffect(() => {
    const checkMobile = () => setIsMobile(window.innerWidth <= 767);
    checkMobile();
    window.addEventListener('resize', checkMobile);
    return () => window.removeEventListener('resize', checkMobile);
  }, []);

  const handleContactMouseDown = (e: React.MouseEvent) => {
    if (e.button === 0) {
      setIsDragging(true);
      hasMovedRef.current = false;
      dragStartRef.current = {
        x: e.clientX,
        y: e.clientY,
      };
    }
  };

  const handleContactMouseMove = (e: MouseEvent) => {
    if (!isDragging) return;

    const deltaX = Math.abs(e.clientX - dragStartRef.current.x);
    const deltaY = Math.abs(e.clientY - dragStartRef.current.y);

    if (deltaX > 5 || deltaY > 5) {
      hasMovedRef.current = true;
    }

    const newY = Math.max(60, Math.min(window.innerHeight - 60, e.clientY - (dragStartRef.current.y - contactPosition.y)));

    setContactPosition(prev => ({ x: prev.x, y: newY }));
  };

  const handleContactMouseUp = () => {
    const moved = hasMovedRef.current;
    setIsDragging(false);
    hasMovedRef.current = false;

    if (!moved) {
      setContactModalOpen(true);
    }
  };

  useEffect(() => {
    if (isDragging) {
      document.addEventListener('mousemove', handleContactMouseMove);
      document.addEventListener('mouseup', handleContactMouseUp);
      return () => {
        document.removeEventListener('mousemove', handleContactMouseMove);
        document.removeEventListener('mouseup', handleContactMouseUp);
      };
    }
  }, [isDragging]);

  const loadUnreadCount = () => {
    getUnreadCount().then(count => {
      setUnreadCount(count);
    }).catch(() => { });
  };

  useEffect(() => {
    getMenuConfigs().then(data => {
      const items = data.filter((m: any) => m.is_active !== false && m.isActive !== false);
      setMenuItems(items);
    }).catch(() => { });
    loadCreditCatalog();
    getPaymentMethods().then(data => {
      setEnabledMethods(data);
      if (data.alipay) setPaymentMethod('alipay');
      else if (data.wechat) setPaymentMethod('wechat');
    }).catch(() => { });
  }, []);

  useEffect(() => {
    if (user) {
      loadUnreadCount();
    }
  }, [user?.id, user?.credits]);

  useEffect(() => {
    const checkPendingOrder = async () => {
      const savedOrderStr = localStorage.getItem(PENDING_ORDER_KEY);
      if (savedOrderStr) {
        try {
          const savedOrder = JSON.parse(savedOrderStr);
          const order = await getPaymentOrder(savedOrder.orderNo);
          if (order.status === 'pending') {
            setCurrentPaymentInfo({
              price: savedOrder.price,
              credits: savedOrder.credits,
              qrCode: savedOrder.qrCode,
              method: savedOrder.method,
              title: savedOrder.title || '会员服务',
            });
            currentOrderNoRef.current = savedOrder.orderNo;
            const now = Date.now();
            const createdAt = new Date(savedOrder.createdAt).getTime();
            const timeoutSeconds = savedOrder.timeoutSeconds || 180;
            const elapsedSeconds = Math.floor((now - createdAt) / 1000);
            const remainingSeconds = Math.max(0, timeoutSeconds - elapsedSeconds);

            if (remainingSeconds > 0) {
              setQrCodeModalOpen(true);
              startPolling(savedOrder.orderNo, remainingSeconds);
            } else {
              localStorage.removeItem(PENDING_ORDER_KEY);
            }
          } else if (order.status === 'paid') {
            message.success('支付成功！积分已到账');
            useAuthStore.getState().refreshUser();
            localStorage.removeItem(PENDING_ORDER_KEY);
          } else {
            localStorage.removeItem(PENDING_ORDER_KEY);
          }
        } catch {
          localStorage.removeItem(PENDING_ORDER_KEY);
        }
      }
    };
    checkPendingOrder();
  }, []);

  const selectedKey = location.pathname.startsWith('/records') ? '/records' : location.pathname;
  const sidebarW = SIDEBAR_W;

  const childMap: Record<string, MenuConfig[]> = {};
  menuItems.forEach(m => {
    const pid = m.parent_id ?? m.parentId;
    if (pid) {
      if (!childMap[pid]) childMap[pid] = [];
      childMap[pid].push(m);
    }
  });

  const topLevelItems = menuItems.filter(m => !(m.parent_id ?? m.parentId));
  topLevelItems.sort((a, b) => {
    const orderA = typeof a.sortOrder === 'number' ? a.sortOrder : Infinity;
    const orderB = typeof b.sortOrder === 'number' ? b.sortOrder : Infinity;
    return orderA - orderB;
  });

  Object.keys(childMap).forEach(key => {
    childMap[key].sort((a, b) => {
      const orderA = typeof a.sortOrder === 'number' ? a.sortOrder : Infinity;
      const orderB = typeof b.sortOrder === 'number' ? b.sortOrder : Infinity;
      return orderA - orderB;
    });
  });

  const handleMobileMenuClick = (item: MenuConfig) => {
    const menuType = item.menu_type ?? item.menuType;
    const hasChildren = childMap[item.id] && childMap[item.id].length > 0;

    if (menuType === 'group' || hasChildren) {
      setMobileExpandedMenus(prev => ({
        ...prev,
        [item.id]: !prev[item.id]
      }));
    } else if (item.path) {
      navigate(item.path);
      setMobileMenuOpen(false);
    }
  };

  const userMenuItems = [
    { key: 'profile', icon: <UserOutlined />, label: `账号: ${user?.username}`, disabled: true },
    { key: 'credits', icon: <WalletOutlined style={{ color: '#c9a96e' }} />, label: `积分: ${user?.credits ?? 0}`, disabled: true },
    { type: 'divider' as const },
    ...(user?.isTeamManager ? [{ key: 'teamManagement' as const, icon: <TeamOutlined style={{ color: '#6366f1' }} />, label: '团队管理' }] : []),
    { key: 'myCredits', icon: <WalletOutlined />, label: '积分明细' },
    { key: 'orderRecords', icon: <FileTextOutlined />, label: '订单记录' },
    { key: 'invoice', icon: <ProfileOutlined />, label: '申请开票' },
    { key: 'messages', icon: <BellOutlined />, label: `消息中心${unreadCount > 0 ? `(${unreadCount})` : ''}` },
    ...(operationManualUrl ? [{ key: 'manual' as const, icon: <FileTextOutlined />, label: '操作手册' }] : []),
    { type: 'divider' as const },
    { key: 'changePwd', icon: <LockOutlined />, label: '个人信息' },
    { type: 'divider' as const },
    { key: 'logout', icon: <LogoutOutlined />, label: '退出登录', danger: true },
  ];

  const handleUserMenuClick = ({ key }: { key: string }) => {
    if (key === 'logout') { logout(); navigate('/login'); }
    else if (key === 'changePwd') { setPwdModalOpen(true); }
    else if (key === 'messages') { navigate('/messages'); }
    else if (key === 'recharge') { setRechargeModalOpen(true); }
    else if (key === 'teamManagement') { navigate('/team-management'); }
    else if (key === 'myCredits') { navigate('/user-center?tab=credits'); }
    else if (key === 'orderRecords') { navigate('/user-center?tab=orders'); }
    else if (key === 'invoice') { navigate('/invoice'); }
    else if (key === 'manual') { window.open(operationManualUrl, '_blank'); }
  };

  const handleChangePwd = async () => {
    try {
      const values = await pwdForm.validateFields();
      await changePassword(values.oldPwd, values.newPwd);
      message.success('密码修改成功');
      setPwdModalOpen(false);
      pwdForm.resetFields();
    } catch (error: any) {
      if (error?.response?.data?.detail) {
        message.error(error.response.data.detail);
      } else if (error?.message) {
        message.error(error.message);
      }
    }
  };

  const handleChangeUsername = async () => {
    try {
      const values = await usernameForm.validateFields();
      const result = await changeUsername(values.username);
      message.success(result.message || '操作成功');
      await refreshUser();
      getUser().then((res: any) => {
        const rc = res?.resourceCapacity;
        if (rc) {
          setResourceCapacity({
            enabled: !!rc.enabled,
            usedBytes: Number(rc.usedBytes) || 0,
            totalBytes: Number(rc.totalBytes) || 0,
            availableBytes: Number(rc.availableBytes) || 0,
            usagePercent: Number(rc.usagePercent) || 0,
            exceeded: !!rc.exceeded,
            limitValue: rc.limitValue ?? '',
            limitUnit: rc.limitUnit || 'GB',
          });
        }
      }).catch(() => { });
      setPwdModalOpen(false);
      usernameForm.resetFields();
    } catch (error: any) {
      if (error?.response?.data?.message) {
        message.error(error.response.data.message);
      } else if (error?.response?.data?.detail) {
        message.error(error.response.data.detail);
      } else if (error?.message) {
        message.error(error.message);
      }
    }
  };

  const handleLogout = () => {
    logout();
    navigate('/login');
  };

  const stopPolling = useCallback(() => {
    if (pollingTimerRef.current) {
      clearInterval(pollingTimerRef.current);
      pollingTimerRef.current = null;
    }
    if (countdownTimerRef.current) {
      clearInterval(countdownTimerRef.current);
      countdownTimerRef.current = null;
    }
  }, []);

  const handleDirectPurchase = useCallback(async (
    productId: string,
    product: { name?: string; price?: number; currentPrice?: number; monthlyGrantCredits?: number | string; credits?: number; grantCredits?: number; regularPrice?: number; originalPrice?: number; billingCycle?: string; tierCode?: string; description?: string; }
  ) => {
    if (!enabledMethods.alipay && !enabledMethods.wechat) {
      message.error('暂无可用支付方式');
      return;
    }
    setPaying(true);
    try {
      const order = await createRechargeOrder(productId, paymentMethod);
      const qrCode = order.qrUrl || order.codeUrl || order.qr_code || order.code_url;
      const finalPrice = Number(order.amount ?? product.currentPrice ?? product.price ?? 0);
      const credits = Number(product.grantCredits || product.monthlyGrantCredits || 0);
      const originalPrice = product.regularPrice ?? product.originalPrice;
      const cycleMap: Record<string, string> = { monthly: '月套餐', quarterly: '季套餐', yearly: '年套餐' };
      const isSubscription = !!product.billingCycle;
      const periodLabel = product.billingCycle ? cycleMap[product.billingCycle] : '';
      const tierName = product.name || '积分充值';
      const displayTitle = isSubscription ? `${tierName} ${periodLabel}` : tierName;
      const paymentInfo = {
        price: finalPrice,
        credits,
        qrCode,
        method: order.paymentMethod,
        title: displayTitle,
        originalPrice: originalPrice ? Number(originalPrice) : undefined,
        discountAmount: originalPrice ? Number(originalPrice) - finalPrice : undefined,
        tierName,
        periodLabel,
        isSubscription,
      };
      if ((order.paymentMethod === 'alipay' || order.paymentMethod === 'wechat') && qrCode) {
        setCurrentPaymentInfo(paymentInfo);
        setCreditsModalOpen(false);
        setQrCodeModalOpen(true);
        currentOrderNoRef.current = order.orderNo;
        localStorage.setItem(PENDING_ORDER_KEY, JSON.stringify({
          orderNo: order.orderNo,
          ...paymentInfo,
          createdAt: order.createdAt || new Date().toISOString(),
          timeoutSeconds: 180,
        }));
        startPolling(order.orderNo);
      } else {
        message.success('购买成功，积分已到账');
        await useAuthStore.getState().refreshUser();
        await loadCreditCatalog();
        setSelectedPlan(null);
      }
    } catch (err: any) {
      message.error(err?.message || '创建订单失败');
    } finally {
      setPaying(false);
    }
  }, [paymentMethod, enabledMethods]);

  const startPolling = useCallback((orderNo: string, timeoutSeconds: number = 180) => {
    stopPolling();
    setCountdown(timeoutSeconds);

    const pollingTimer = setInterval(async () => {
      try {
        const order = await getPaymentOrder(orderNo);
        if (order.status === 'paid') {
          stopPolling();
          currentOrderNoRef.current = null;
          localStorage.removeItem(PENDING_ORDER_KEY);
          message.success('支付成功！积分已到账');
          useAuthStore.getState().refreshUser();
          loadCreditCatalog();
          setQrCodeModalOpen(false);
          setCurrentPaymentInfo(null);
          setSelectedPlan(null);
        } else if (order.status === 'cancelled') {
          stopPolling();
          currentOrderNoRef.current = null;
          localStorage.removeItem(PENDING_ORDER_KEY);
        }
      } catch {
      }
    }, 2000);
    pollingTimerRef.current = pollingTimer;

    const countdownTimer = setInterval(() => {
      setCountdown(prev => {
        if (prev <= 1) {
          stopPolling();
          if (currentOrderNoRef.current) {
            cancelPaymentOrder(currentOrderNoRef.current).catch(() => { });
            currentOrderNoRef.current = null;
          }
          localStorage.removeItem(PENDING_ORDER_KEY);
          message.warning('订单已超时，请重新充值');
          setQrCodeModalOpen(false);
          setCurrentPaymentInfo(null);
          setSelectedPlan(null);
          return 0;
        }
        return prev - 1;
      });
    }, 1000);
    countdownTimerRef.current = countdownTimer;
  }, [loadCreditCatalog, stopPolling]);

  const handleContactSubmit = async () => {
    if (!user) {
      message.warning('请先登录');
      return;
    }
    try {
      const values = await contactForm.validateFields();
      setSubmittingContact(true);
      await createContactRequest({
        phone: values.phone,
        company_name: values.companyName,
        industry: values.industry,
        name: values.name,
        message: values.message,
      });
      message.success('提交成功，我们会尽快与您联系');
      setContactModalOpen(false);
      contactForm.resetFields();
    } catch (err: any) {
      message.error(err?.message || '提交失败');
    } finally {
      setSubmittingContact(false);
    }
  };

  const renderMenuItem = (item: MenuConfig, depth: number = 0) => {
    const isActive = item.path === selectedKey;
    const menuIcon = iconMap[item.icon] || <HomeOutlined />;
    const hasChildren = childMap[item.id] && childMap[item.id].length > 0;
    const menuType = item.menu_type ?? item.menuType;
    const isGroup = menuType === 'group';

    return (
      <div key={item.id}>
        <div
          onClick={() => {
            if (!(isGroup || hasChildren) && item.path) {
              navigate(item.path);
            }
          }}
          style={{
            display: 'flex', alignItems: 'center',
            justifyContent: 'flex-start',
            gap: 10,
            padding: depth > 0 ? '6px 12px 6px 32px' : '6px 14px',
            borderRadius: 12, margin: '1px 4px',
            cursor: isGroup || hasChildren ? 'default' : 'pointer',
            fontSize: depth > 0 ? 13 : 14, fontWeight: isActive ? 600 : 400,
            color: isActive ? '#4f46e5' : (isGroup ? '#94a3b8' : '#475569'),
            background: isActive ? 'linear-gradient(135deg, rgba(99, 102, 241, 0.1) 0%, rgba(139, 92, 246, 0.08) 100%)' : 'transparent',
            transition: 'all 0.2s ease',
          }}
          onMouseEnter={(e) => {
            if (!isGroup && !isActive && !(isGroup || hasChildren)) {
              e.currentTarget.style.background = 'rgba(99, 102, 241, 0.05)';
            }
          }}
          onMouseLeave={(e) => {
            if (!isActive) {
              e.currentTarget.style.background = 'transparent';
            }
          }}
        >
          {!isGroup && (
            <span style={{
              fontSize: depth > 0 ? 14 : 16,
              flexShrink: 0,
              color: isActive ? '#6366f1' : '#64748b',
            }}>{menuIcon}</span>
          )}
          <span style={{ whiteSpace: 'nowrap', flex: 1, textAlign: 'left', fontWeight: isGroup ? 600 : (isActive ? 600 : 400), fontSize: isGroup ? 12 : (depth > 0 ? 13 : 14), textTransform: isGroup ? 'uppercase' : 'none', letterSpacing: isGroup ? 0.5 : 0 }}>
            {item.label}
          </span>
        </div>

        {(isGroup || hasChildren) && (
          <div style={{ overflow: 'hidden' }}>
            {(childMap[item.id] || []).map(c => renderMenuItem(c, depth + 1))}
          </div>
        )}
      </div>
    );
  };

  return (
    <Layout style={{
      height: '100vh',
      display: 'flex',
      flexDirection: 'column',
      overflow: 'hidden',
    }}>
      <ActivityBanner onVisibilityChange={(v) => setBannerVisible(v)} />
      <div style={{ display: 'flex', position: 'relative', padding: 4, gap: 12, flex: 1, minHeight: 0, overflow: 'hidden' }}>
        <div className="desktop-sidebar" style={{
          width: sidebarW, position: 'sticky', top: 4, alignSelf: 'flex-start', zIndex: 100,
          height: '100%',
          background: 'linear-gradient(180deg, #ffffff 0%, #f8fafc 100%)',
          borderRadius: '20px',
          boxShadow: '0 4px 32px rgba(0, 0, 0, 0.06), 0 1px 8px rgba(0, 0, 0, 0.04)',
          display: 'flex', flexDirection: 'column',
          transition: 'width 0.25s ease',
          overflow: 'hidden',
          border: '1px solid rgba(0, 0, 0, 0.06)',
        }}>
          <div style={{
            height: 80, display: 'flex', alignItems: 'center',
            justifyContent: 'flex-start',
            padding: '0 20px',
            flexShrink: 0,
            background: 'linear-gradient(135deg, rgba(99, 102, 241, 0.06) 0%, rgba(139, 92, 246, 0.04) 100%)',
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 14, cursor: 'pointer' }}
              onClick={() => {
                navigate('/home');
              }}>
              <div style={{
                width: 42, height: 42, borderRadius: 14, flexShrink: 0,
                //background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #a78bfa 100%)',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                boxShadow: '0 4px 16px rgba(99, 102, 241, 0.35)',
                overflow: 'hidden',
              }}

              >
                {siteLogo ? (
                  <img src={siteLogo} alt="logo" style={{ width: 36, height: 36, objectFit: 'contain' }} />
                ) : (
                  <ThunderboltOutlined style={{ fontSize: 20, color: '#ffffff' }} />
                )}
              </div>
              <span style={{
                color: '#1e293b', fontSize: 17, fontWeight: 700, letterSpacing: -0.02,
                whiteSpace: 'nowrap',
                background: 'linear-gradient(135deg, #6366f1, #8b5cf6)',
                WebkitBackgroundClip: 'text',
                WebkitTextFillColor: 'transparent',
                backgroundClip: 'text',
              }}>
                {siteName}
              </span>
            </div>
          </div>

          <div style={{ flex: 1, padding: '8px 8px', overflow: 'auto' }}>
            {topLevelItems.map(item => renderMenuItem(item))}
          </div>

          <div onClick={() => setRechargeModalOpen(true)} style={{
            margin: '8px 12px',
            padding: '12px 20px',
            borderRadius: 14, cursor: 'pointer',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            gap: 8,
            color: '#ffffff', fontSize: 14, fontWeight: 600,
            background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)',
            boxShadow: '0 4px 16px rgba(99, 102, 241, 0.4)',
            transition: 'all 0.3s ease',
          }}
            onMouseEnter={(e) => {
              e.currentTarget.style.background = 'linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%)';
              e.currentTarget.style.transform = 'translateY(-1px)';
              e.currentTarget.style.boxShadow = '0 6px 20px rgba(99, 102, 241, 0.5)';
            }}
            onMouseLeave={(e) => {
              e.currentTarget.style.background = 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)';
              e.currentTarget.style.transform = 'translateY(0)';
              e.currentTarget.style.boxShadow = '0 4px 16px rgba(99, 102, 241, 0.4)';
            }}
          >
            <PlusOutlined style={{ fontSize: 16 }} />
            <span>充值积分</span>
          </div>
          {/* 资源存储容量展示（来自 getUser.resourceCapacity） */}
          <StorageCard data={resourceCapacity} />

          <div style={{ padding: '16px 16px', flexShrink: 0, paddingTop: 0 }}>
            <Dropdown menu={{ items: userMenuItems, onClick: handleUserMenuClick }} placement="topRight" arrow>
              <div className="user-card-container" style={{
                padding: '10px 14px',
                display: 'flex', alignItems: 'center',
                justifyContent: 'flex-start',
                gap: 12,
                borderRadius: 14, cursor: 'pointer',
                transition: 'all 0.35s cubic-bezier(0.4,0,0.2,1)',
                background: 'linear-gradient(135deg, rgba(248, 250, 252, 0.95) 0%, rgba(241, 245, 249, 0.95) 100%)',
                boxShadow: '0 2px 12px rgba(0, 0, 0, 0.04), inset 0 1px 0 rgba(255,255,255,0.8)',
                position: 'relative',
                border: '1px solid rgba(99, 102, 241, 0.15)',
                animation: 'cardBreath 3s ease-in-out infinite',
              }}
                onMouseEnter={(e) => {
                  e.currentTarget.style.background = 'linear-gradient(135deg, #ffffff 0%, #f8fafc 100%)';
                  e.currentTarget.style.boxShadow = '0 8px 24px rgba(99, 102, 241, 0.25), inset 0 1px 0 rgba(255,255,255,0.9)';
                  e.currentTarget.style.transform = 'translateY(-3px) scale(1.01)';
                  e.currentTarget.style.borderColor = 'rgba(99, 102, 241, 0.4)';
                  e.currentTarget.style.animation = 'none';
                  e.currentTarget.querySelector('.user-card-arrow')?.classList.add('arrow-hover');
                }}
                onMouseLeave={(e) => {
                  e.currentTarget.style.background = 'linear-gradient(135deg, rgba(248, 250, 252, 0.95) 0%, rgba(241, 245, 249, 0.95) 100%)';
                  e.currentTarget.style.boxShadow = '0 2px 12px rgba(0, 0, 0, 0.04), inset 0 1px 0 rgba(255,255,255,0.8)';
                  e.currentTarget.style.transform = 'translateY(0) scale(1)';
                  e.currentTarget.style.borderColor = 'rgba(99, 102, 241, 0.15)';
                  e.currentTarget.style.animation = 'cardBreath 3s ease-in-out infinite';
                  e.currentTarget.querySelector('.user-card-arrow')?.classList.remove('arrow-hover');
                }}
              >
                <div className="user-card-glow" style={{
                  position: 'absolute',
                  inset: -4,
                  borderRadius: 18,
                  background: 'linear-gradient(90deg, transparent 0%, rgba(99,102,241,0.15) 25%, rgba(139,92,246,0.15) 50%, rgba(99,102,241,0.15) 75%, transparent 100%)',
                  backgroundSize: '200% 100%',
                  opacity: 0.8,
                  animation: 'borderShimmer 2.5s linear infinite',
                  pointerEvents: 'none',
                }} />

                <Avatar size={36} icon={<UserOutlined />}
                  style={{
                    background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)',
                    flexShrink: 0,
                    boxShadow: '0 4px 12px rgba(99, 102, 241, 0.3)',
                    transition: 'all 0.35s cubic-bezier(0.4,0,0.2,1)',
                    position: 'relative',
                    zIndex: 1,
                    animation: 'avatarPulse 2s ease-in-out infinite',
                  }} />

                <div style={{ flex: 1, minWidth: 0, position: 'relative', zIndex: 1 }}>
                  <div style={{ color: '#1e293b', fontSize: 16, fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', letterSpacing: -0.01 }}>
                    {user?.username}
                  </div>
                  <div style={{
                    color: '#6366f1',
                    fontSize: 14,
                    fontWeight: 500,
                    letterSpacing: 0,
                    borderRadius: 6,
                    display: 'inline-block',
                    animation: 'creditGlow 1.5s ease-in-out infinite',
                  }}>积分: {user?.credits || 0}</div>
                </div>

                <div className="user-card-arrow" style={{
                  fontSize: 12,
                  color: '#6366f1',
                  flexShrink: 0,
                  position: 'relative',
                  zIndex: 1,
                }}>
                  <MenuOutlined />
                </div>

                <style>{`
                @keyframes arrowFlash {
                  0%, 100% {
                    transform: translateY(0) scale(1);
                    opacity: 0.6;
                    filter: drop-shadow(0 0 4px rgba(99, 102, 241, 0.4));
                  }
                  50% {
                    transform: translateY(4px) scale(1.1);
                    opacity: 1;
                    filter: drop-shadow(0 0 12px rgba(99, 102, 241, 0.7));
                  }
                }
                @keyframes creditGlow {
                  0%, 100% {
                    text-shadow: 0 0 0 transparent;
                  }
                  50% {
                    text-shadow: 0 0 15px rgba(99, 102, 241, 0.6), 0 0 30px rgba(99, 102, 241, 0.3);
                  }
                }
                @keyframes borderShimmer {
                  0% { background-position: 200% center; }
                  100% { background-position: -200% center; }
                }
                @keyframes cardBreath {
                  0%, 100% {
                    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04), inset 0 1px 0 rgba(255,255,255,0.8);
                    border-color: rgba(99, 102, 241, 0.15);
                  }
                  50% {
                    box-shadow: 0 4px 20px rgba(99, 102, 241, 0.1), inset 0 1px 0 rgba(255,255,255,0.8);
                    border-color: rgba(99, 102, 241, 0.25);
                  }
                }
                @keyframes avatarPulse {
                  0%, 100% {
                    box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
                    transform: scale(1);
                  }
                  50% {
                    box-shadow: 0 6px 20px rgba(99, 102, 241, 0.5);
                    transform: scale(1.02);
                  }
                }
                .user-card-arrow.arrow-hover {
                  color: #8b5cf6 !important;
                  transform: rotate(180deg) scale(1.15) !important;
                  animation: none !important;
                  filter: drop-shadow(0 0 15px rgba(139, 92, 246, 0.8)) !important;
                }
              `}</style>
              </div>
            </Dropdown>


          </div>
        </div>

        <div className="desktop-content" style={{
          flex: 1,
          background: '#f1f2f3',
          borderRadius: '20px',
          boxShadow: '0 4px 32px rgba(0, 0, 0, 0.06), 0 1px 8px rgba(0, 0, 0, 0.04)',
          padding: '24px 32px 32px',
          border: '1px solid rgba(0, 0, 0, 0.06)',
          overflow: 'auto',
          minHeight: 0,
        }}>
          {!isMobile && <Outlet context={{ openContactModal: () => setContactModalOpen(true) }} />}
        </div>
      </div>

      <div className="mobile-header">
        <div className="mobile-header-content">
          <div className="mobile-menu-btn" onClick={() => setMobileMenuOpen(true)}>
            <MenuOutlined style={{ fontSize: 20 }} />
          </div>
          <div className="mobile-header-title">{siteName}</div>
          <div className="mobile-header-right">
            <div className="mobile-credits-badge" onClick={() => setRechargeModalOpen(true)}>
              <WalletOutlined />
              <span>{user?.credits || 0}</span>
            </div>
          </div>
        </div>
      </div>

      <div className="mobile-content">
        {isMobile && <Outlet context={{ openContactModal: () => setContactModalOpen(true) }} />}
      </div>

      <Drawer
        title={
          <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
            <div style={{
              width: 36, height: 36, borderRadius: 10, flexShrink: 0,
              background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #a78bfa 100%)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              boxShadow: '0 4px 12px rgba(99, 102, 241, 0.35)',
            }}>
              {siteLogo ? (
                <img src={siteLogo} alt="logo" style={{ width: 24, height: 24, objectFit: 'contain' }} />
              ) : (
                <ThunderboltOutlined style={{ fontSize: 18, color: '#ffffff' }} />
              )}
            </div>
            <span style={{ fontWeight: 700, fontSize: 16, color: '#1e293b' }}>{siteName}</span>
          </div>
        }
        placement="left"
        onClose={() => setMobileMenuOpen(false)}
        open={mobileMenuOpen}
        size={280}
        closable={true}
        className="mobile-menu-drawer"
        styles={{
          header: { borderBottom: '1px solid #f1f5f9', padding: '16px 20px' },
          body: { padding: '12px 8px', display: 'flex', flexDirection: 'column' },
        }}
      >
        <div style={{ flex: 1, overflow: 'auto', paddingBottom: 12 }}>
          <div style={{ padding: '12px 8px 16px' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 16 }}>
              <Avatar size={44} style={{ background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)', flexShrink: 0 }}>
                <UserOutlined />
              </Avatar>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 15, fontWeight: 600, color: '#1e293b', marginBottom: 2 }}>
                  {user?.username || '用户'}
                </div>
                <div style={{ fontSize: 13, color: '#64748b' }}>
                  <WalletOutlined style={{ color: '#f59e0b', marginRight: 4 }} />
                  积分: <span style={{ color: '#f59e0b', fontWeight: 600 }}>{user?.credits ?? 0}</span>
                </div>
              </div>
            </div>
          </div>

          {/* 资源存储容量展示（与桌面端共用 StorageCard） */}
          <StorageCard data={resourceCapacity} />

          {topLevelItems.map(item => {
            const menuType = item.menu_type ?? item.menuType;
            const hasChildren = childMap[item.id] && childMap[item.id].length > 0;
            const isActive = item.path === selectedKey;
            const isExpanded = mobileExpandedMenus[item.id];
            const menuIcon = iconMap[item.icon] || <HomeOutlined />;

            return (
              <div key={item.id}>
                <div
                  className={`mobile-menu-item ${isActive && !hasChildren ? 'mobile-menu-item-active' : ''} ${menuType === 'group' ? 'mobile-menu-group' : ''}`}
                  onClick={() => handleMobileMenuClick(item)}
                >
                  {menuType !== 'group' && (
                    <span className="mobile-menu-icon" style={{ color: isActive ? '#6366f1' : '#64748b' }}>
                      {menuIcon}
                    </span>
                  )}
                  <span className="mobile-menu-label" style={{
                    paddingLeft: menuType === 'group' ? 0 : 0,
                    color: menuType === 'group' ? '#94a3b8' : (isActive ? '#4f46e5' : '#475569'),
                    fontWeight: menuType === 'group' ? 600 : (isActive ? 600 : 400),
                    fontSize: menuType === 'group' ? 12 : 15,
                    textTransform: menuType === 'group' ? 'uppercase' : 'none',
                    letterSpacing: menuType === 'group' ? 0.5 : 0,
                  }}>
                    {item.label}
                  </span>
                  {(menuType === 'group' || hasChildren) && (
                    <span style={{
                      fontSize: 12,
                      color: '#cbd5e1',
                      transition: 'transform 0.2s ease',
                      transform: isExpanded ? 'rotate(90deg)' : 'rotate(0deg)',
                    }}>
                      <RightOutlined />
                    </span>
                  )}
                </div>
                {(menuType === 'group' || hasChildren) && isExpanded && (
                  <div className="mobile-submenu">
                    {(childMap[item.id] || []).map(child => {
                      const childActive = child.path === selectedKey;
                      const childIcon = iconMap[child.icon] || <HomeOutlined />;
                      return (
                        <div
                          key={child.id}
                          className={`mobile-menu-item mobile-submenu-item ${childActive ? 'mobile-menu-item-active' : ''}`}
                          onClick={() => handleMobileMenuClick(child)}
                        >
                          <span className="mobile-menu-icon" style={{ color: childActive ? '#6366f1' : '#94a3b8' }}>
                            {childIcon}
                          </span>
                          <span className="mobile-menu-label" style={{
                            color: childActive ? '#4f46e5' : '#64748b',
                            fontWeight: childActive ? 600 : 400,
                            fontSize: 14,
                          }}>
                            {child.label}
                          </span>
                        </div>
                      );
                    })}
                  </div>
                )}
              </div>
            );
          })}
        </div>

        <div style={{ padding: '8px 0', borderTop: '1px solid #f1f5f9' }}>
          <div
            className="mobile-menu-item"
            onClick={() => {
              navigate('/user-center?tab=credits');
              setMobileMenuOpen(false);
            }}
          >
            <span className="mobile-menu-icon" style={{ color: '#f59e0b' }}>
              <WalletOutlined />
            </span>
            <span className="mobile-menu-label" style={{ color: '#475569' }}>积分明细</span>
          </div>

          <div
            className="mobile-menu-item"
            onClick={() => {
              navigate('/user-center?tab=orders');
              setMobileMenuOpen(false);
            }}
          >
            <span className="mobile-menu-icon" style={{ color: '#6366f1' }}>
              <FileTextOutlined />
            </span>
            <span className="mobile-menu-label" style={{ color: '#475569' }}>订单记录</span>
          </div>

          <div
            className="mobile-menu-item"
            onClick={() => {
              navigate('/messages');
              setMobileMenuOpen(false);
            }}
          >
            <span className="mobile-menu-icon" style={{ color: '#8b5cf6' }}>
              <BellOutlined />
            </span>
            <span className="mobile-menu-label" style={{ color: '#475569' }}>
              消息中心
              {unreadCount > 0 && (
                <Tag color="red" style={{ marginLeft: 8, fontSize: 11 }}>{unreadCount}</Tag>
              )}
            </span>
          </div>

          <div
            className="mobile-menu-item"
            onClick={() => {
              setPwdModalOpen(true);
              setMobileMenuOpen(false);
            }}
          >
            <span className="mobile-menu-icon" style={{ color: '#0ea5e9' }}>
              <LockOutlined />
            </span>
            <span className="mobile-menu-label" style={{ color: '#475569' }}>个人信息</span>
          </div>

          <div style={{ height: 8 }} />

          <div
            className="mobile-menu-item mobile-recharge-item"
            onClick={() => {
              setRechargeModalOpen(true);
              setMobileMenuOpen(false);
            }}
          >
            <span className="mobile-menu-icon" style={{ color: '#fff' }}>
              <PlusOutlined />
            </span>
            <span className="mobile-menu-label" style={{ color: '#fff', fontWeight: 600 }}>充值积分</span>
          </div>

          <div
            className="mobile-menu-item"
            onClick={() => {
              handleLogout();
              setMobileMenuOpen(false);
            }}
          >
            <span className="mobile-menu-icon" style={{ color: '#ef4444' }}>
              <LogoutOutlined />
            </span>
            <span className="mobile-menu-label" style={{ color: '#ef4444' }}>退出登录</span>
          </div>
        </div>
      </Drawer>

      <Modal title={<Space><SettingOutlined />账号设置</Space>} open={pwdModalOpen}
        onCancel={() => { setPwdModalOpen(false); pwdForm.resetFields(); usernameForm.resetFields(); }}
        width={440}
        footer={null}>
        <Tabs defaultActiveKey="profile">
          <Tabs.TabPane tab="个人信息" key="profile">
            <Form form={usernameForm} layout="vertical" style={{ marginTop: 20 }} onValuesChange={() => { }}>
              <Form.Item name="username" label="用户名" rules={[{ required: true, message: '请输入用户名' }, { min: 3, message: '用户名至少3位' }]}>
                <Input placeholder="请输入用户名" size="large" prefix={<UserOutlined style={{ color: '#94a3b8', marginRight: 8 }} />} />
              </Form.Item>
              <Form.Item>
                <Button type="primary" size="large" onClick={handleChangeUsername} style={{ width: '100%' }}>确认修改</Button>
              </Form.Item>
            </Form>
          </Tabs.TabPane>
          <Tabs.TabPane tab="修改密码" key="password">
            <Form form={pwdForm} layout="vertical" style={{ marginTop: 20 }} onValuesChange={() => { }}>
              <Form.Item name="oldPwd" label="原密码" rules={[{ required: true, message: '请输入原密码' }]}>
                <Input.Password placeholder="请输入原密码" size="large" prefix={<LockOutlined style={{ color: '#94a3b8', marginRight: 8 }} />} />
              </Form.Item>
              <Form.Item name="newPwd" label="新密码" rules={[{ required: true, message: '请输入新密码' }, { min: 6, message: '密码至少6位' }]}>
                <Input.Password placeholder="请输入新密码（至少6位）" size="large" prefix={<LockOutlined style={{ color: '#94a3b8', marginRight: 8 }} />} />
              </Form.Item>
              <Form.Item name="confirmPwd" label="确认新密码" rules={[
                { required: true, message: '请再次输入新密码' },
                ({ getFieldValue }: any) => ({
                  validator(_: any, value: string) {
                    if (!value || getFieldValue('newPwd') === value) return Promise.resolve();
                    return Promise.reject(new Error('两次密码不一致'));
                  },
                }),
              ]}>
                <Input.Password placeholder="请再次输入新密码" size="large" prefix={<LockOutlined style={{ color: '#94a3b8', marginRight: 8 }} />} />
              </Form.Item>
              <Form.Item>
                <Button type="primary" size="large" onClick={handleChangePwd} style={{ width: '100%' }}>确认修改</Button>
              </Form.Item>
            </Form>
          </Tabs.TabPane>
        </Tabs>
      </Modal>

      {/* 充值全屏弹窗 */}
      <ConfigProvider
        theme={{
          token: {
            colorPrimary: '#6366f1',
            borderRadius: 8,
          },
        }}
      >
        <Modal
          open={rechargeModalOpen}
          onCancel={() => setRechargeModalOpen(false)}
          footer={null}
          width="100%"
          centered={false}
          style={{ top: 0, maxWidth: '100vw', margin: 0, paddingBottom: 0 }}
          styles={{
            body: { padding: 0, height: '100vh', overflow: 'auto', scrollbarWidth: 'none', msOverflowStyle: 'none' },
            mask: { background: 'rgba(0,0,0,0.45)' },
            header: { display: 'none' },
          }}
          closable
          className="recharge-fullscreen-modal"
          title={null}
          closeIcon={<CloseOutlined style={{ fontSize: 18 }} />}
        >
          <div style={{
            width: '100%',
            minHeight: '100vh',
            background: '#f8fafc',
            position: 'relative',
          }}>
            <div style={{ maxWidth: 1200, margin: '0 auto', padding: '24px' }}>
              {/* 订阅套餐区 */}
              <div style={{ marginBottom: 24 }}>
                <div style={{ textAlign: 'center', marginBottom: 20 }}>
                  <Typography.Title level={3} style={{ marginBottom: 8 }}>订阅套餐</Typography.Title>
                  <Typography.Text type="secondary">订阅积分按自然月逐月发放；有效订阅只能升级同周期更高等级套餐，不能提前续费。</Typography.Text>
                </div>

                {currentSubscription && (
                  <div style={{ marginBottom: 16, padding: '14px 16px', borderRadius: 12, background: '#fff', border: '1px solid #e8eaed', display: 'flex', alignItems: 'center', gap: 16 }}>
                    <div style={{
                      width: 40, height: 40, borderRadius: 10, flexShrink: 0,
                      background: 'linear-gradient(135deg, #6366f1, #8b5cf6)',
                      display: 'flex', alignItems: 'center', justifyContent: 'center',
                      color: '#fff', fontSize: 18,
                    }}>
                      <CrownOutlined />
                    </div>
                    <div style={{ flex: 1 }}>
                      <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 4 }}>
                        <Typography.Text strong style={{ fontSize: 14 }}>
                          当前订阅：{currentSubscription.tierCode || '订阅套餐'}
                        </Typography.Text>
                        <Tag color="purple" style={{ fontSize: 11, margin: 0, borderRadius: 6 }}>
                          {currentSubscription.billingCycle === 'monthly' ? '月' : currentSubscription.billingCycle === 'quarterly' ? '季' : '年'}
                        </Tag>
                      </div>
                      <div style={{ fontSize: 12, color: '#64748b', marginBottom: 2 }}>
                        已发放 <span style={{ color: '#6366f1', fontWeight: 600 }}>{currentSubscription.grantedCount}</span>/{currentSubscription.grantCount} 期
                        · 每月 <span style={{ color: '#6366f1', fontWeight: 600 }}>{Number(currentSubscription.monthlyGrantCredits || 0).toLocaleString()}</span> 积分
                      </div>
                      <div style={{ fontSize: 11, color: '#94a3b8' }}>
                        订阅到期：{new Date(currentSubscription.expiresAt).toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai', hour12: false })}
                      </div>
                    </div>
                    <Progress
                      percent={Math.round(((currentSubscription.grantedCount || 0) / (currentSubscription.grantCount || 1)) * 100)}
                      size="small"
                      strokeColor={{ from: '#6366f1', to: '#8b5cf6' }}
                      style={{ width: 80 }}
                    />
                  </div>
                )}

                <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 16, marginBottom: 20 }}>
                  <Radio.Group value={selectedPeriod} onChange={(e) => { setSelectedPeriod(e.target.value); setSelectedPlan(null); }} buttonStyle="solid">
                    <Radio.Button value="monthly">月套餐</Radio.Button>
                    <Radio.Button value="quarterly">季套餐</Radio.Button>
                    <Radio.Button value="yearly">年套餐</Radio.Button>
                  </Radio.Group>
                </div>

                {subscriptionProducts.filter((item) => item.billingCycle === selectedPeriod).length === 0 ? (
                  <div style={{ padding: 48, textAlign: 'center', color: '#94a3b8' }}>暂无可订阅套餐，请联系管理员配置并上架套餐。</div>
                ) : (
                  <div style={{ display: 'flex', justifyContent: 'center', gap: 16, flexWrap: 'wrap' }}>
                    {subscriptionProducts.filter((item) => item.billingCycle === selectedPeriod).map((product, index) => {
                      const gradient = MEMBERSHIP_GRADIENTS[index % MEMBERSHIP_GRADIENTS.length];
                      const originalPrice = product.regularPrice || product.price;
                      const currentPrice = product.currentPrice ?? product.price;
                      const hasDiscount = originalPrice && Number(originalPrice) > Number(currentPrice);
                      const creditsLabel = product.monthlyGrantCredits
                        ? `${Number(product.monthlyGrantCredits).toLocaleString()} 积分/月`
                        : `${Number(product.grantCredits || 0).toLocaleString()} 积分`;
                      return (
                        <div key={product.id} style={{
                          width: 250,
                          display: 'flex', flexDirection: 'column',
                          borderRadius: 14, overflow: 'hidden',
                          background: '#fff',
                          border: '1px solid #e8eaed',
                          position: 'relative',
                          transition: 'all 0.2s',
                        }}>
                          <div style={{ padding: '16px 14px 12px', background: '#fafbfc', flex: 1 }}>
                            {product.priceType === 'first_purchase' && (
                              <div style={{ position: 'absolute', top: 8, right: 8, background: '#fff2e8', color: '#fa541c', fontSize: 11, padding: '2px 8px', borderRadius: 10, fontWeight: 500 }}>首充价</div>
                            )}
                            {product.priceType === 'activity' && (
                              <div style={{ position: 'absolute', top: 8, right: 8, background: '#fff1f0', color: '#cf1322', fontSize: 11, padding: '2px 8px', borderRadius: 10, fontWeight: 500 }}>活动价</div>
                            )}
                            <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
                              <div style={{ width: 32, height: 32, borderRadius: 8, background: gradient.gradient, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontSize: 14 }}>{gradient.icon}</div>
                              <div>
                                <Typography.Text strong style={{ fontSize: 14 }}>{product.name}</Typography.Text>
                                <div style={{ fontSize: 11, color: '#94a3b8' }}>{product.description || product.tierCode}</div>
                              </div>
                            </div>
                            <div style={{ marginBottom: 8 }}>
                              <span style={{ fontSize: 24, fontWeight: 700, color: '#1a1a2e' }}>¥{currentPrice}</span>
                              {hasDiscount && (
                                <span style={{ fontSize: 13, color: '#94a3b8', textDecoration: 'line-through', marginLeft: 6 }}>¥{originalPrice}</span>
                              )}
                              {product.canUpgrade && (
                                <Tag color="orange" style={{ marginLeft: 6, fontSize: 10, padding: '0 6px', lineHeight: '16px' }}>升级价</Tag>
                              )}
                            </div>
                            {product.canUpgrade && Number(product.deductionAmount || 0) > 0 && (
                              <div style={{ fontSize: 11, color: '#94a3b8', marginBottom: 4 }}>
                                目标套餐¥{product.targetPrice}，抵扣未生效¥{product.deductionAmount}
                              </div>
                            )}
                            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', fontSize: 12, color: '#64748b' }}>
                              <span>{creditsLabel}</span>
                              <span>共 {product.grantCount} 次</span>
                            </div>
                            {product.unavailableReason && (
                              <div style={{ padding: '6px 14px', fontSize: 13, color: '#dc2626', background: '#fef2f2', marginTop: '20px' }}>
                                {product.unavailableReason}
                              </div>
                            )}
                            <div style={{ padding: '10px 14px', borderTop: '1px solid #f0f0f0' }}>
                              <Button
                                block
                                size="small"
                                disabled={product.canPurchase === false || (!enabledMethods.alipay && !enabledMethods.wechat)}
                                loading={paying && selectedPlan === product.id}
                                onClick={() => {
                                  setSelectedPlan(product.id);
                                  handleDirectPurchase(product.id, product);
                                }}
                                style={{
                                  borderRadius: 8,
                                  background: product.canPurchase === false ? '#f5f5f5' : 'linear-gradient(135deg, #6366f1, #8b5cf6)',
                                  color: product.canPurchase === false ? '#94a3b8' : '#fff',
                                  border: 'none',
                                  fontWeight: 600,
                                  height: 34,
                                  fontSize: 13,
                                }}
                              >
                                {product.canPurchase === false ? '不可购买' : '立即订阅'}
                              </Button>
                            </div>
                            {product.features && product.features.length > 0 && (
                              <div style={{ marginTop: 10, paddingTop: 10, borderTop: '1px dashed #e2e8f0' }}>
                                {product.features.map((feature: string, fi: number) => (
                                  <div key={fi} style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12, color: '#64748b', lineHeight: '20px', marginBottom: 2 }}>
                                    <CheckCircleFilled style={{ color: '#4c49cc', fontSize: 14, flexShrink: 0, marginTop: 2 }} />
                                    <span style={{ fontSize: 14, margin: '4px' }}>{feature}</span>
                                  </div>
                                ))}
                              </div>
                            )}
                            {(product.priceType === 'first_purchase' || product.priceType === 'activity') && (
                              <div style={{ padding: '10px 14px', background: '#fffbe6', borderTop: '1px solid #fff1b8' }}>
                                <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 6 }}>
                                  <FireOutlined style={{ color: '#fa8c16', fontSize: 12 }} />
                                  <span style={{ fontSize: 12, color: '#d46b08', fontWeight: 600 }}>限时活动</span>
                                </div>
                                {product.features?.slice(0, 3).map((feature: string, fi: number) => (
                                  <div key={fi} style={{ fontSize: 11, color: '#8c6d1f', lineHeight: '18px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                                    · {feature}
                                  </div>
                                ))}
                              </div>
                            )}
                          </div>
                        </div>
                      );
                    })}
                  </div>
                )}
              </div>

              {/* 积分充值入口 */}
              <div style={{ marginBottom: 24, background: '#fff', borderRadius: 12, padding: 24, border: '1px solid #e8eaed' }}>
                <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                    <WalletOutlined style={{ color: '#6366f1', fontSize: 24 }} />
                    <div>
                      <Typography.Title level={4} style={{ margin: 0 }}>积分充值</Typography.Title>
                      <Typography.Text type="secondary" style={{ fontSize: 12 }}>当前积分：<span style={{ color: '#6366f1', fontWeight: 600 }}>{user?.credits ?? 0}</span></Typography.Text>
                    </div>
                  </div>
                  <Button
                    type="primary"
                    size="large"
                    icon={<ShoppingCartOutlined />}
                    onClick={() => setCreditsModalOpen(true)}
                    style={{
                      borderRadius: 10,
                      background: 'linear-gradient(135deg, #6366f1, #8b5cf6)',
                      border: 'none',
                      height: 42,
                      paddingLeft: 20,
                      paddingRight: 20,
                    }}
                  >
                    积分商城
                  </Button>
                </div>
              </div>

              {/* 常见问题 - 浅色背景 */}
              <div style={{ marginBottom: 24, borderRadius: 16, overflow: 'hidden', background: '#fff', border: '1px solid #e8eaed' }}>
                <div style={{ padding: '24px 24px 0', textAlign: 'center' }}>
                  <Typography.Title level={3} style={{ color: '#1a1a2e', marginBottom: 16 }}>常见问题</Typography.Title>
                </div>
                <Collapse
                  accordion
                  expandIcon={({ isActive }) => isActive ? <UpOutlined style={{ color: '#64748b' }} /> : <DownOutlined style={{ color: '#64748b' }} />}
                  style={{ background: '#fff', border: 'none' }}
                  items={FAQ_ITEMS.map(item => ({
                    key: item.key,
                    label: <span style={{ color: '#1a1a2e', fontSize: 14, fontWeight: 500 }}>{item.label}</span>,
                    children: item.children,
                    style: { background: '#fff', borderBottom: '1px solid #e8eaed' },
                  }))}
                />

                {/* 联系客服按钮 */}
                <div style={{
                  padding: '24px',
                  borderTop: '1px solid #e8eaed',
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'space-between',
                  cursor: 'pointer',
                  transition: 'background 0.2s',
                }}
                  onClick={() => { setContactModalOpen(true); }}
                  onMouseEnter={(e) => { e.currentTarget.style.background = '#f8fafc'; }}
                  onMouseLeave={(e) => { e.currentTarget.style.background = '#fff'; }}
                >
                  <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                    <MessageOutlined style={{ color: '#64748b', fontSize: 18 }} />
                    <span style={{ color: '#1a1a2e', fontSize: 14, fontWeight: 500 }}>联系客服</span>
                  </div>
                  <RightOutlined style={{ color: '#64748b', fontSize: 14 }} />
                </div>
              </div>
            </div>
          </div>
        </Modal>
      </ConfigProvider>

      {/* 积分商城弹窗 */}
      <Modal
        title={<Space><WalletOutlined />积分商城</Space>}
        open={creditsModalOpen}
        onCancel={() => setCreditsModalOpen(false)}
        footer={null}
        width={720}
        closable
        styles={{ body: { padding: 20 } }}
      >
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 }}>
          <Space>
            <Typography.Text>当前积分：</Typography.Text>
            <Typography.Text strong style={{ color: '#6366f1', fontSize: 18 }}>{user?.credits ?? 0}</Typography.Text>
          </Space>
        </div>

        {/* <div style={{ display: 'flex', gap: 12, marginBottom: 16 }}>
          {enabledMethods.alipay && (
            <div onClick={() => setPaymentMethod('alipay')} style={{ flex: 1, textAlign: 'center', borderRadius: 10, height: 44, lineHeight: '42px', border: paymentMethod === 'alipay' ? '2px solid #1677ff' : '1px solid #e8eaed', color: paymentMethod === 'alipay' ? '#1677ff' : '#64748b', cursor: 'pointer', background: paymentMethod === 'alipay' ? '#f0f7ff' : '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6, transition: 'all 0.2s' }}>
              <AlipayCircleOutlined style={{ fontSize: 16 }} />支付宝
            </div>
          )}
          {enabledMethods.wechat && (
            <div onClick={() => setPaymentMethod('wechat')} style={{ flex: 1, textAlign: 'center', borderRadius: 10, height: 44, lineHeight: '42px', border: paymentMethod === 'wechat' ? '2px solid #07c160' : '1px solid #e8eaed', color: paymentMethod === 'wechat' ? '#07c160' : '#64748b', cursor: 'pointer', background: paymentMethod === 'wechat' ? '#f0fff4' : '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6, transition: 'all 0.2s' }}>
              <WechatOutlined style={{ fontSize: 16 }} />微信支付
            </div>
          )}
        </div> */}

        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(160px, 1fr))', gap: 12, maxHeight: 400, overflowY: 'auto', paddingRight: 4 }}>
          {rechargeOptions.length === 0 && <div style={{ width: '100%', padding: 32, textAlign: 'center', color: '#94a3b8' }}>暂无可购买的积分增值包</div>}
          {rechargeOptions.map((opt, idx) => {
            const g = GRADIENTS[idx % GRADIENTS.length];
            const totalCredits = Number(opt.grantCredits || 0);
            const currentPrice = opt.currentPrice || opt.price;
            return (
              <div key={opt.id} style={{ borderRadius: 12, overflow: 'hidden', background: '#fff', border: selectedPlan === opt.id ? '2px solid #e8eaed' : '1px solid #e8eaed', position: 'relative', transition: 'all 0.2s' }}>
                {opt.description && (
                  <div style={{ position: 'absolute', top: -1, right: 8, background: '#fff2e8', color: '#fa541c', fontSize: 11, padding: '2px 8px', borderRadius: 10, fontWeight: 500 }}>{opt.description}</div>
                )}
                <div style={{ padding: '12px 10px 8px', background: '#fafbfc' }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 4 }}>
                    <div style={{ width: 32, height: 32, borderRadius: 8, flexShrink: 0, background: g.gradient, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 14, color: '#fff' }}>{g.icon}</div>
                    <div>
                      <Typography.Text strong style={{ fontSize: 12 }}>{opt.name}</Typography.Text>
                      <div style={{ fontSize: 11, fontWeight: 600, color: '#6366f1' }}>{totalCredits.toLocaleString()} 积分</div>
                    </div>
                  </div>
                  <div style={{ marginTop: 4, fontSize: 18, fontWeight: 700, color: '#1a1a2e' }}>¥{currentPrice}</div>
                  <Typography.Text type="secondary" style={{ fontSize: 10 }}>有效期 {Number(opt.validityMonths || 1)} 个月</Typography.Text>
                </div>
                <div style={{ padding: '6px 10px', borderTop: '1px solid #f0f0f0' }}>
                  <Button block size="small" disabled={!enabledMethods.alipay && !enabledMethods.wechat} loading={paying && selectedPlan === opt.id} onClick={() => { setSelectedPlan(opt.id); handleDirectPurchase(opt.id, opt); }} style={{ borderRadius: 6, background: 'linear-gradient(135deg, #6366f1, #8b5cf6)', color: '#fff', border: 'none', fontWeight: 600, height: 28, fontSize: 12 }}>购买</Button>
                </div>
              </div>
            );
          })}
        </div>
      </Modal>

      {/* QR 支付弹窗 */}
      <Modal
        open={qrCodeModalOpen}
        onCancel={async () => {
          stopPolling();
          if (currentOrderNoRef.current) {
            try { await cancelPaymentOrder(currentOrderNoRef.current); } catch { }
            currentOrderNoRef.current = null;
          }
          localStorage.removeItem(PENDING_ORDER_KEY);
          setQrCodeModalOpen(false);
          setCurrentPaymentInfo(null);
        }}
        footer={
          <div style={{ display: 'flex', justifyContent: 'center', padding: '8px 0' }}>
            <Button
              danger
              size="large"
              onClick={async () => {
                stopPolling();
                if (currentOrderNoRef.current) {
                  try { await cancelPaymentOrder(currentOrderNoRef.current); } catch { }
                  currentOrderNoRef.current = null;
                }
                localStorage.removeItem(PENDING_ORDER_KEY);
                setQrCodeModalOpen(false);
                setCurrentPaymentInfo(null);
                message.info('已取消支付');
              }}
              style={{ borderRadius: 10, minWidth: 140, fontSize: 14 }}
            >
              取消支付
            </Button>
          </div>
        }
        width={700}
        closable
        title={
          <Typography.Title level={5} style={{ margin: 0 }}>
            开通{currentPaymentInfo?.title || '会员服务'}{currentPaymentInfo?.credits ? ` ${Number(currentPaymentInfo.credits).toLocaleString()} 积分` : ''}
          </Typography.Title>
        }
        styles={{
          body: { padding: 0, borderRadius: 16, overflow: 'hidden' },
          footer: { borderRadius: 16, borderTop: '1px solid #f0f0f0', padding: '16px 24px' },
        }}
      >
        <div style={{ display: 'flex', minHeight: 380 }}>
          <div style={{ flex: 1, padding: 24, background: '#fff', borderRight: '1px solid #f0f0f0' }}>
            <div style={{ marginBottom: 20 }}>
              <Typography.Text style={{ fontSize: 13, color: '#64748b', marginBottom: 8, display: 'block' }}>商品信息</Typography.Text>
              <div style={{ padding: 14, background: '#f8fafc', borderRadius: 10, border: '1px solid #e2e8f0' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}>
                  <div style={{ fontSize: 14, fontWeight: 600, color: '#1a1a2e' }}>
                    {currentPaymentInfo?.tierName || currentPaymentInfo?.title || '积分充值'}
                  </div>
                  {currentPaymentInfo?.periodLabel && (
                    <Tag color="purple" style={{ fontSize: 11, margin: 0, borderRadius: 6, padding: '0 6px' }}>
                      {currentPaymentInfo.periodLabel}
                    </Tag>
                  )}
                </div>
                <div style={{ fontSize: 22, fontWeight: 700, color: '#6366f1', lineHeight: 1.4 }}>
                  ¥{currentPaymentInfo?.price || 0}
                  {currentPaymentInfo?.originalPrice && Number(currentPaymentInfo.originalPrice) > Number(currentPaymentInfo?.price || 0) && (
                    <span style={{ fontSize: 13, color: '#94a3b8', textDecoration: 'line-through', marginLeft: 8, fontWeight: 400 }}>
                      ¥{currentPaymentInfo.originalPrice}
                    </span>
                  )}
                </div>
              </div>
            </div>
            <div>
              <Typography.Text style={{ fontSize: 13, color: '#64748b', marginBottom: 8, display: 'block' }}>订单明细</Typography.Text>
              <div style={{ padding: 12, background: '#f8fafc', borderRadius: 8, border: '1px solid #e2e8f0' }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', padding: '4px 0', fontSize: 12 }}>
                  <span style={{ color: '#64748b' }}>积分数量</span>
                  <span style={{ color: '#1a1a2e' }}>
                    {currentPaymentInfo?.credits != null ? `${Number(currentPaymentInfo.credits).toLocaleString()} 积分` : '-'}
                  </span>
                </div>
                <div style={{ display: 'flex', justifyContent: 'space-between', padding: '4px 0', fontSize: 12 }}>
                  <span style={{ color: '#64748b' }}>续费信息</span>
                  <span style={{ color: '#1a1a2e' }}>
                    {currentPaymentInfo?.isSubscription ? '次年按原价 可随时取消' : '一次性购买'}
                  </span>
                </div>
                <div style={{ height: 1, background: '#e2e8f0', margin: '8px 0' }} />
                <div style={{ display: 'flex', justifyContent: 'space-between', padding: '4px 0', fontSize: 12 }}>
                  <span style={{ color: '#64748b' }}>商品原价</span>
                  <span style={{ color: '#1a1a2e' }}>¥{currentPaymentInfo?.originalPrice || currentPaymentInfo?.price || 0}.00</span>
                </div>
                <div style={{ height: 1, background: '#e2e8f0', margin: '8px 0' }} />
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '4px 0' }}>
                  <span style={{ fontSize: 14, fontWeight: 500, color: '#1a1a2e' }}>应付金额</span>
                  <span style={{ fontSize: 18, fontWeight: 700, color: '#6366f1' }}>
                    ¥{currentPaymentInfo?.price || 0}.00
                  </span>
                </div>
              </div>
            </div>
          </div>

          <div style={{ width: 280, padding: 24, background: '#fff', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 12 }}>
              {currentPaymentInfo?.method === 'alipay'
                ? <AlipayCircleOutlined style={{ fontSize: 18, color: '#1677ff' }} />
                : <WechatOutlined style={{ fontSize: 18, color: '#07c160' }} />}
              <span style={{ fontSize: 14, color: '#64748b' }}>
                请用{currentPaymentInfo?.method === 'alipay' ? '支付宝' : '微信'}扫码支付
              </span>
            </div>
            <div style={{ width: 180, height: 180, borderRadius: 12, border: '1px solid #f0f0f0', display: 'flex', alignItems: 'center', justifyContent: 'center', background: '#fff' }}>
              {currentPaymentInfo?.qrCode && (
                <QRCodeSVG value={currentPaymentInfo.qrCode} size={150} level="M" />
              )}
            </div>
            <div style={{ marginTop: 12, fontSize: 12, color: '#94a3b8' }}>
              {countdown}秒后二维码失效
            </div>
            <div style={{ marginTop: 8, fontSize: 11, color: '#94a3b8', textAlign: 'center' }}>
              开通即代表同意<br />《用户服务协议》
            </div>
          </div>
        </div>
      </Modal>

      <NotificationPopup />

      <div
        className="contact-button-wrapper"
        style={{
          right: `${contactPosition.x}px`,
          bottom: `${window.innerHeight - contactPosition.y}px`,
        }}
      >
        <div style={{
          position: 'relative',
        }}>
          <div
            className="contact-tooltip"
            style={{
              opacity: contactHovered ? 1 : 0,
            }}
          >
            联系我们
          </div>
          <button
            className={`contact-button ${isDragging ? 'dragging' : ''}`}
            onMouseEnter={() => setContactHovered(true)}
            onMouseLeave={() => setContactHovered(false)}
            onMouseDown={handleContactMouseDown}
            onMouseUp={handleContactMouseUp}
          >
            <MessageOutlined style={{ fontSize: 20 }} />
          </button>
        </div>
      </div>

      <Modal
        title={<Space><MessageOutlined />联系我们</Space>}
        open={contactModalOpen}
        onCancel={() => { setContactModalOpen(false); contactForm.resetFields(); }}
        footer={null}
        width={480}
        className="contact-modal"
      >
        <div style={{ marginTop: 8 }}>
          <Form form={contactForm} layout="vertical">
            <Form.Item
              name="name"
              label="姓名"
              rules={[{ required: true, message: '请输入姓名' }]}
            >
              <Input placeholder="请输入您的姓名" size="large" />
            </Form.Item>
            <Form.Item
              name="phone"
              label="手机号"
              rules={[
                { required: true, message: '请输入手机号' },
                { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号' },
              ]}
            >
              <Input placeholder="请输入您的手机号" size="large" />
            </Form.Item>
            <Form.Item
              name="companyName"
              label="公司名称"
              rules={[{ required: true, message: '请输入公司名称' }]}
            >
              <Input placeholder="请输入公司名称" size="large" />
            </Form.Item>
            <Form.Item
              name="industry"
              label="您的行业"
              rules={[{ required: true, message: '请输入您的行业' }]}
            >
              <Input placeholder="请输入您的行业" size="large" />
            </Form.Item>
            <Form.Item name="message" label="留言（选填）">
              <Input.TextArea
                placeholder="请输入您的需求或问题"
                rows={3}
                style={{ borderRadius: 10 }}
              />
            </Form.Item>
          </Form>
          <div style={{ marginTop: 16, display: 'flex', gap: 12 }}>
            <Button
              size="large"
              onClick={() => { setContactModalOpen(false); contactForm.resetFields(); }}
              style={{ borderRadius: 10, flex: 1 }}
            >
              取消
            </Button>
            <Button
              type="primary"
              size="large"
              onClick={handleContactSubmit}
              loading={submittingContact}
              style={{
                borderRadius: 10,
                background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)',
                border: 'none',
                flex: 1,
              }}
            >
              提交
            </Button>
          </div>
        </div>
      </Modal>

    </Layout>
  );
};

export default AppLayout;
