flutter实现web端实现效果

flutter实现web端实现效果

效果图


flutter 版本 sdk: '>=3.4.4 <4.0.0'

代码示例

新代码

dart 复制代码
import 'package:flutter/material.dart';

void main() {
  runApp(const NavigationRailApp());
}

class NavigationRailApp extends StatelessWidget {
  const NavigationRailApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'NavigationRail Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        useMaterial3: true,
      ),
      home: const MainNavigationScreen(),
    );
  }
}

class MainNavigationScreen extends StatefulWidget {
  const MainNavigationScreen({super.key});

  @override
  State<MainNavigationScreen> createState() => _MainNavigationScreenState();
}

class _MainNavigationScreenState extends State<MainNavigationScreen> {
  int _selectedMainIndex = 0;
  int _selectedSubIndex = 0;
  int _selectedDetailIndex = 0;

  final List<NavigationCategory> _categories = [
    NavigationCategory(
      title: '产品管理',
      icon: Icons.shopping_bag,
      subCategories: [
        SubCategory(
          title: '手机数码',
          items: [
            DetailItem(
                title: 'iPhone 15 Pro', description: '苹果最新旗舰手机', price: 7999),
            DetailItem(
                title: '三星 Galaxy S24', description: '三星旗舰智能手机', price: 5999),
            DetailItem(title: '小米 14', description: '性价比旗舰手机', price: 3999),
          ],
        ),
        SubCategory(
          title: '家用电器',
          items: [
            DetailItem(title: '智能电视', description: '4K超高清智能电视', price: 2999),
            DetailItem(title: '空调冰箱', description: '节能变频空调冰箱', price: 4599),
          ],
        ),
      ],
    ),
    NavigationCategory(
      title: '用户管理',
      icon: Icons.people,
      subCategories: [
        SubCategory(
          title: '会员用户',
          items: [
            DetailItem(title: 'VIP会员', description: '高级会员特权', price: 299),
            DetailItem(title: '普通用户', description: '基础用户功能', price: 0),
          ],
        ),
        SubCategory(
          title: '权限管理',
          items: [
            DetailItem(title: '角色权限', description: '权限分配管理', price: 0),
            DetailItem(title: '操作日志', description: '系统操作记录', price: 0),
          ],
        ),
      ],
    ),
    NavigationCategory(
      title: '订单管理',
      icon: Icons.receipt,
      subCategories: [
        SubCategory(
          title: '待处理订单',
          items: [
            DetailItem(title: '待付款', description: '等待用户付款的订单', price: 0),
            DetailItem(title: '待发货', description: '等待商家发货的订单', price: 0),
          ],
        ),
        SubCategory(
          title: '已完成订单',
          items: [
            DetailItem(title: '已完成', description: '交易完成的订单', price: 0),
            DetailItem(title: '已评价', description: '用户已评价的订单', price: 0),
          ],
        ),
      ],
    ),
  ];
  final List<GlobalKey<NavigatorState>> _rightNavigatorKeys = [
    GlobalKey<NavigatorState>(),
    GlobalKey<NavigatorState>(),
    GlobalKey<NavigatorState>(),
    GlobalKey<NavigatorState>(),
    GlobalKey<NavigatorState>(),
    GlobalKey<NavigatorState>(),
  ];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: [
          // 固定左侧导航栏
          FixedNavigationRail(
            categories: _categories,
            selectedMainIndex: _selectedMainIndex,
            selectedSubIndex: _selectedSubIndex,
            onMainIndexChanged: (index) {
              setState(() {
                _selectedMainIndex = index;
                _selectedSubIndex = 0;
                _selectedDetailIndex = 0;
              });
            },
            onSubIndexChanged: (index) {
              setState(() {
                _selectedSubIndex = index;
                _selectedDetailIndex = 0;
              });
            },
          ),
          // 右侧内容区域
          const VerticalDivider(thickness: 1, width: 1),
          Expanded(
            child: Navigator(
              key: _rightNavigatorKeys[_selectedDetailIndex],
              onGenerateRoute: (RouteSettings settings) {
                return MaterialPageRoute(
                  builder: (BuildContext context) {
                    return _buildContentArea();
                  },
                );
              },
            ),
          ),

          // 右侧内容区域
          // Expanded(
          //   child: _buildContentArea(),
          // ),
        ],
      ),
    );
  }

  Widget _buildContentArea() {
    return Container(
      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: Alignment.topLeft,
          end: Alignment.bottomRight,
          colors: [
            Colors.blue.shade50,
            Colors.white,
          ],
        ),
      ),
      child: _categories[_selectedMainIndex].buildContent(
        selectedSubIndex: _selectedSubIndex,
        selectedDetailIndex: _selectedDetailIndex,
        onSubIndexChanged: (index) {
          setState(() {
            _selectedSubIndex = index;
            _selectedDetailIndex = 0;
          });
        },
        onDetailIndexChanged: (index) {
          setState(() {
            _selectedDetailIndex = index;
          });
        },
      ),
    );
  }
}

class NavigationCategory {
  final String title;
  final IconData icon;
  final List<SubCategory> subCategories;

  NavigationCategory({
    required this.title,
    required this.icon,
    required this.subCategories,
  });

  Widget buildContent({
    required int selectedSubIndex,
    required int selectedDetailIndex,
    required ValueChanged<int> onSubIndexChanged,
    required ValueChanged<int> onDetailIndexChanged,
  }) {
    return CategoryContentPage(
      category: this,
      selectedSubIndex: selectedSubIndex,
      selectedDetailIndex: selectedDetailIndex,
      onSubIndexChanged: onSubIndexChanged,
      onDetailIndexChanged: onDetailIndexChanged,
    );
  }
}

class SubCategory {
  final String title;
  final List<DetailItem> items;

  SubCategory({
    required this.title,
    required this.items,
  });
}

class DetailItem {
  final String title;
  final String description;
  final double price;

  DetailItem({
    required this.title,
    required this.description,
    required this.price,
  });
}

class FixedNavigationRail extends StatelessWidget {
  final List<NavigationCategory> categories;
  final int selectedMainIndex;
  final int selectedSubIndex;
  final ValueChanged<int> onMainIndexChanged;
  final ValueChanged<int> onSubIndexChanged;

  const FixedNavigationRail({
    super.key,
    required this.categories,
    required this.selectedMainIndex,
    required this.selectedSubIndex,
    required this.onMainIndexChanged,
    required this.onSubIndexChanged,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 280,
      decoration: BoxDecoration(
        color: Colors.white,
        boxShadow: [
          BoxShadow(
            color: Colors.grey.withOpacity(0.3),
            blurRadius: 10,
            offset: const Offset(2, 0),
          ),
        ],
        border: Border(
          right: BorderSide(
            color: Colors.grey.shade200,
            width: 1,
          ),
        ),
      ),
      child: Column(
        children: [
          _buildHeaderSection(),
          _buildMainNavigationSection(),
        ],
      ),
    );
  }

  Widget _buildHeaderSection() {
    return Container(
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        border: Border(
          bottom: BorderSide(
            color: Colors.grey.shade200,
            width: 1,
          ),
        ),
      ),
      child: const Row(
        children: [
          Icon(Icons.dashboard, color: Colors.blue, size: 24),
          SizedBox(width: 12),
          Text(
            '管理系统',
            style: TextStyle(
              fontSize: 18,
              fontWeight: FontWeight.bold,
              color: Colors.blue,
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildMainNavigationSection() {
    return Expanded(
      child: ListView.builder(
        itemCount: categories.length,
        itemBuilder: (context, index) {
          return _buildMainCategoryItem(categories[index], index);
        },
      ),
    );
  }

  Widget _buildMainCategoryItem(NavigationCategory category, int index) {
    final isSelected = index == selectedMainIndex;

    return Column(
      children: [
        ListTile(
          leading: Icon(
            category.icon,
            color: isSelected ? Colors.blue : Colors.grey.shade600,
          ),
          title: Text(
            category.title,
            style: TextStyle(
              fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
              color: isSelected ? Colors.blue : Colors.grey.shade800,
            ),
          ),
          tileColor: isSelected ? Colors.blue.shade50 : Colors.transparent,
          selected: isSelected,
          onTap: () => onMainIndexChanged(index),
        ),
        if (isSelected) ..._buildSubCategoryItems(category),
      ],
    );
  }

  List<Widget> _buildSubCategoryItems(NavigationCategory category) {
    return category.subCategories.asMap().entries.map((entry) {
      final subIndex = entry.key;
      final subCategory = entry.value;
      final isSubSelected = subIndex == selectedSubIndex;

      return Padding(
        padding: const EdgeInsets.only(left: 16),
        child: ListTile(
          leading: Icon(
            Icons.folder,
            color: isSubSelected ? Colors.blue : Colors.grey.shade600,
          ),
          title: Text(
            subCategory.title,
            style: TextStyle(
              fontSize: 14,
              color: isSubSelected ? Colors.blue : Colors.grey.shade700,
            ),
          ),
          tileColor: isSubSelected ? Colors.blue.shade50 : Colors.transparent,
          selected: isSubSelected,
          onTap: () => onSubIndexChanged(subIndex),
        ),
      );
    }).toList();
  }
}

class CategoryContentPage extends StatelessWidget {
  final NavigationCategory category;
  final int selectedSubIndex;
  final int selectedDetailIndex;
  final ValueChanged<int> onSubIndexChanged;
  final ValueChanged<int> onDetailIndexChanged;

  const CategoryContentPage({
    super.key,
    required this.category,
    required this.selectedSubIndex,
    required this.selectedDetailIndex,
    required this.onSubIndexChanged,
    required this.onDetailIndexChanged,
  });

  @override
  Widget build(BuildContext context) {
    final subCategory = category.subCategories[selectedSubIndex];

    return Padding(
      padding: const EdgeInsets.all(24),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          _buildPageHeader(),
          const SizedBox(height: 20),
          _buildSubCategorySelector(),
          const SizedBox(height: 20),
          Expanded(
            child: _buildContentGrid(subCategory),
          ),
        ],
      ),
    );
  }

  Widget _buildPageHeader() {
    return Row(
      children: [
        Icon(category.icon, color: Colors.blue, size: 32),
        const SizedBox(width: 12),
        Text(
          category.title,
          style: const TextStyle(
            fontSize: 28,
            fontWeight: FontWeight.bold,
            color: Colors.blue,
          ),
        ),
      ],
    );
  }

  Widget _buildSubCategorySelector() {
    return SingleChildScrollView(
      scrollDirection: Axis.horizontal,
      child: Row(
        children: category.subCategories.asMap().entries.map((entry) {
          final index = entry.key;
          final subCategory = entry.value;
          final isSelected = index == selectedSubIndex;

          return Padding(
            padding: const EdgeInsets.only(right: 12),
            child: ChoiceChip(
              label: Text(subCategory.title),
              selected: isSelected,
              onSelected: (selected) {
                if (selected) onSubIndexChanged(index);
              },
            ),
          );
        }).toList(),
      ),
    );
  }

  Widget _buildContentGrid(SubCategory subCategory) {
    return GridView.builder(
      gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 3,
        crossAxisSpacing: 16,
        mainAxisSpacing: 16,
        childAspectRatio: 1.2,
      ),
      itemCount: subCategory.items.length,
      itemBuilder: (context, index) {
        return _buildItemCard(context, subCategory.items[index], index);
      },
    );
  }

  Widget _buildItemCard(BuildContext context, DetailItem item, int index) {
    return Card(
      elevation: 4,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(12),
      ),
      child: InkWell(
        borderRadius: BorderRadius.circular(12),
        onTap: () {
          onDetailIndexChanged(index);
          _navigateToDetailPage(context, item);
        },
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Icon(Icons.description, color: Colors.blue, size: 32),
              const SizedBox(height: 8),
              Text(
                item.title,
                style: const TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.w500,
                ),
              ),
              const SizedBox(height: 4),
              Text(
                item.description,
                style: TextStyle(
                  fontSize: 12,
                  color: Colors.grey.shade600,
                ),
              ),
              const Spacer(),
              if (item.price > 0)
                Text(
                  '¥${item.price}',
                  style: const TextStyle(
                    fontSize: 14,
                    fontWeight: FontWeight.bold,
                    color: Colors.green,
                  ),
                ),
            ],
          ),
        ),
      ),
    );
  }

  void _navigateToDetailPage(BuildContext context, DetailItem item) {
    Navigator.of(context).push(
      MaterialPageRoute(
        builder: (context) => ItemDetailPage(item: item),
      ),
    );
  }
}

class ItemDetailPage extends StatelessWidget {
  final DetailItem item;

  const ItemDetailPage({super.key, required this.item});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(item.title),
        backgroundColor: Colors.transparent,
        elevation: 0,
        leading: IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () => Navigator.pop(context),
        ),
      ),
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            _buildDetailHeader(),
            const SizedBox(height: 24),
            _buildDetailContent(),
            const SizedBox(height: 24),
            _buildActionButtons(),
          ],
        ),
      ),
    );
  }

  Widget _buildDetailHeader() {
    return Row(
      children: [
        Container(
          width: 60,
          height: 60,
          decoration: BoxDecoration(
            color: Colors.blue.shade100,
            borderRadius: BorderRadius.circular(12),
          ),
          child: Icon(Icons.description, color: Colors.blue, size: 32),
        ),
        const SizedBox(width: 16),
        Expanded(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                item.title,
                style: const TextStyle(
                  fontSize: 24,
                  fontWeight: FontWeight.bold,
                ),
              ),
              Text(
                item.description,
                style: TextStyle(
                  fontSize: 16,
                  color: Colors.grey.shade600,
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }

  Widget _buildDetailContent() {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(20),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text(
              '详细信息',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 16),
            _buildInfoRow('产品名称', item.title),
            _buildInfoRow('产品描述', item.description),
            if (item.price > 0) _buildInfoRow('价格', '¥${item.price}'),
            const SizedBox(height: 20),
            const Text(
              '操作说明',
              style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
            ),
            const SizedBox(height: 12),
            Text(
              '在这里可以执行相关的操作,如编辑、删除、查看历史记录等。',
              style: TextStyle(color: Colors.grey.shade600),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildInfoRow(String label, String value) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 8),
      child: Row(
        children: [
          SizedBox(
            width: 80,
            child: Text(
              '$label:',
              style: TextStyle(
                fontWeight: FontWeight.w500,
                color: Colors.grey.shade700,
              ),
            ),
          ),
          const SizedBox(width: 12),
          Expanded(
            child: Text(
              value,
              style: const TextStyle(fontSize: 14),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildActionButtons() {
    return Row(
      children: [
        Expanded(
          child: ElevatedButton.icon(
            icon: const Icon(Icons.edit),
            label: const Text('编辑信息'),
            onPressed: () {},
          ),
        ),
        const SizedBox(width: 12),
        Expanded(
          child: OutlinedButton.icon(
            icon: const Icon(Icons.delete),
            label: const Text('删除'),
            onPressed: () {},
          ),
        ),
      ],
    );
  }
}

旧代码

dart 复制代码
import 'package:flutter/material.dart';

void main() {
  runApp(const NavigationRailApp());
}

class NavigationRailApp extends StatelessWidget {
  const NavigationRailApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'NavigationRail Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        useMaterial3: true,
      ),
      home: const MainNavigationScreen(),
    );
  }
}

class MainNavigationScreen extends StatefulWidget {
  const MainNavigationScreen({super.key});

  @override
  State<MainNavigationScreen> createState() => _MainNavigationScreenState();
}

class _MainNavigationScreenState extends State<MainNavigationScreen> {
  int _selectedMainIndex = 0;
  int _selectedSubIndex = 0;
  int _selectedDetailIndex = 0;

  final List<NavigationCategory> _categories = [
    NavigationCategory(
      title: '产品管理',
      icon: Icons.shopping_bag,
      subCategories: [
        SubCategory(
          title: '手机数码',
          items: [
            DetailItem(
                title: 'iPhone 15 Pro', description: '苹果最新旗舰手机', price: 7999),
            DetailItem(
                title: '三星 Galaxy S24', description: '三星旗舰智能手机', price: 5999),
            DetailItem(title: '小米 14', description: '性价比旗舰手机', price: 3999),
          ],
        ),
        SubCategory(
          title: '家用电器',
          items: [
            DetailItem(title: '智能电视', description: '4K超高清智能电视', price: 2999),
            DetailItem(title: '空调冰箱', description: '节能变频空调冰箱', price: 4599),
          ],
        ),
      ],
    ),
    NavigationCategory(
      title: '用户管理',
      icon: Icons.people,
      subCategories: [
        SubCategory(
          title: '会员用户',
          items: [
            DetailItem(title: 'VIP会员', description: '高级会员特权', price: 299),
            DetailItem(title: '普通用户', description: '基础用户功能', price: 0),
          ],
        ),
        SubCategory(
          title: '权限管理',
          items: [
            DetailItem(title: '角色权限', description: '权限分配管理', price: 0),
            DetailItem(title: '操作日志', description: '系统操作记录', price: 0),
          ],
        ),
      ],
    ),
    NavigationCategory(
      title: '订单管理',
      icon: Icons.receipt,
      subCategories: [
        SubCategory(
          title: '待处理订单',
          items: [
            DetailItem(title: '待付款', description: '等待用户付款的订单', price: 0),
            DetailItem(title: '待发货', description: '等待商家发货的订单', price: 0),
          ],
        ),
        SubCategory(
          title: '已完成订单',
          items: [
            DetailItem(title: '已完成', description: '交易完成的订单', price: 0),
            DetailItem(title: '已评价', description: '用户已评价的订单', price: 0),
          ],
        ),
      ],
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: [
          // 固定左侧导航栏
          FixedNavigationRail(
            categories: _categories,
            selectedMainIndex: _selectedMainIndex,
            selectedSubIndex: _selectedSubIndex,
            onMainIndexChanged: (index) {
              setState(() {
                _selectedMainIndex = index;
                _selectedSubIndex = 0;
                _selectedDetailIndex = 0;
              });
            },
            onSubIndexChanged: (index) {
              setState(() {
                _selectedSubIndex = index;
                _selectedDetailIndex = 0;
              });
            },
          ),

          // 右侧内容区域
          Expanded(
            child: _buildContentArea(),
          ),
        ],
      ),
    );
  }

  Widget _buildContentArea() {
    return Container(
      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: Alignment.topLeft,
          end: Alignment.bottomRight,
          colors: [
            Colors.blue.shade50,
            Colors.white,
          ],
        ),
      ),
      child: _categories[_selectedMainIndex].buildContent(
        selectedSubIndex: _selectedSubIndex,
        selectedDetailIndex: _selectedDetailIndex,
        onSubIndexChanged: (index) {
          setState(() {
            _selectedSubIndex = index;
            _selectedDetailIndex = 0;
          });
        },
        onDetailIndexChanged: (index) {
          setState(() {
            _selectedDetailIndex = index;
          });
        },
      ),
    );
  }
}

class NavigationCategory {
  final String title;
  final IconData icon;
  final List<SubCategory> subCategories;

  NavigationCategory({
    required this.title,
    required this.icon,
    required this.subCategories,
  });

  Widget buildContent({
    required int selectedSubIndex,
    required int selectedDetailIndex,
    required ValueChanged<int> onSubIndexChanged,
    required ValueChanged<int> onDetailIndexChanged,
  }) {
    return CategoryContentPage(
      category: this,
      selectedSubIndex: selectedSubIndex,
      selectedDetailIndex: selectedDetailIndex,
      onSubIndexChanged: onSubIndexChanged,
      onDetailIndexChanged: onDetailIndexChanged,
    );
  }
}

class SubCategory {
  final String title;
  final List<DetailItem> items;

  SubCategory({
    required this.title,
    required this.items,
  });
}

class DetailItem {
  final String title;
  final String description;
  final double price;

  DetailItem({
    required this.title,
    required this.description,
    required this.price,
  });
}

class FixedNavigationRail extends StatelessWidget {
  final List<NavigationCategory> categories;
  final int selectedMainIndex;
  final int selectedSubIndex;
  final ValueChanged<int> onMainIndexChanged;
  final ValueChanged<int> onSubIndexChanged;

  const FixedNavigationRail({
    super.key,
    required this.categories,
    required this.selectedMainIndex,
    required this.selectedSubIndex,
    required this.onMainIndexChanged,
    required this.onSubIndexChanged,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 280,
      decoration: BoxDecoration(
        color: Colors.white,
        boxShadow: [
          BoxShadow(
            color: Colors.grey.withOpacity(0.3),
            blurRadius: 10,
            offset: const Offset(2, 0),
          ),
        ],
        border: Border(
          right: BorderSide(
            color: Colors.grey.shade200,
            width: 1,
          ),
        ),
      ),
      child: Column(
        children: [
          _buildHeaderSection(),
          _buildMainNavigationSection(),
        ],
      ),
    );
  }

  Widget _buildHeaderSection() {
    return Container(
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        border: Border(
          bottom: BorderSide(
            color: Colors.grey.shade200,
            width: 1,
          ),
        ),
      ),
      child: const Row(
        children: [
          Icon(Icons.dashboard, color: Colors.blue, size: 24),
          SizedBox(width: 12),
          Text(
            '管理系统',
            style: TextStyle(
              fontSize: 18,
              fontWeight: FontWeight.bold,
              color: Colors.blue,
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildMainNavigationSection() {
    return Expanded(
      child: ListView.builder(
        itemCount: categories.length,
        itemBuilder: (context, index) {
          return _buildMainCategoryItem(categories[index], index);
        },
      ),
    );
  }

  Widget _buildMainCategoryItem(NavigationCategory category, int index) {
    final isSelected = index == selectedMainIndex;

    return Column(
      children: [
        ListTile(
          leading: Icon(
            category.icon,
            color: isSelected ? Colors.blue : Colors.grey.shade600,
          ),
          title: Text(
            category.title,
            style: TextStyle(
              fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
              color: isSelected ? Colors.blue : Colors.grey.shade800,
            ),
          ),
          tileColor: isSelected ? Colors.blue.shade50 : Colors.transparent,
          selected: isSelected,
          onTap: () => onMainIndexChanged(index),
        ),
        if (isSelected) ..._buildSubCategoryItems(category),
      ],
    );
  }

  List<Widget> _buildSubCategoryItems(NavigationCategory category) {
    return category.subCategories.asMap().entries.map((entry) {
      final subIndex = entry.key;
      final subCategory = entry.value;
      final isSubSelected = subIndex == selectedSubIndex;

      return Padding(
        padding: const EdgeInsets.only(left: 16),
        child: ListTile(
          leading: Icon(
            Icons.folder,
            color: isSubSelected ? Colors.blue : Colors.grey.shade600,
          ),
          title: Text(
            subCategory.title,
            style: TextStyle(
              fontSize: 14,
              color: isSubSelected ? Colors.blue : Colors.grey.shade700,
            ),
          ),
          tileColor: isSubSelected ? Colors.blue.shade50 : Colors.transparent,
          selected: isSubSelected,
          onTap: () => onSubIndexChanged(subIndex),
        ),
      );
    }).toList();
  }
}

class CategoryContentPage extends StatelessWidget {
  final NavigationCategory category;
  final int selectedSubIndex;
  final int selectedDetailIndex;
  final ValueChanged<int> onSubIndexChanged;
  final ValueChanged<int> onDetailIndexChanged;

  const CategoryContentPage({
    super.key,
    required this.category,
    required this.selectedSubIndex,
    required this.selectedDetailIndex,
    required this.onSubIndexChanged,
    required this.onDetailIndexChanged,
  });

  @override
  Widget build(BuildContext context) {
    final subCategory = category.subCategories[selectedSubIndex];

    return Padding(
      padding: const EdgeInsets.all(24),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          _buildPageHeader(),
          const SizedBox(height: 20),
          _buildSubCategorySelector(),
          const SizedBox(height: 20),
          Expanded(
            child: _buildContentGrid(subCategory),
          ),
        ],
      ),
    );
  }

  Widget _buildPageHeader() {
    return Row(
      children: [
        Icon(category.icon, color: Colors.blue, size: 32),
        const SizedBox(width: 12),
        Text(
          category.title,
          style: const TextStyle(
            fontSize: 28,
            fontWeight: FontWeight.bold,
            color: Colors.blue,
          ),
        ),
      ],
    );
  }

  Widget _buildSubCategorySelector() {
    return SingleChildScrollView(
      scrollDirection: Axis.horizontal,
      child: Row(
        children: category.subCategories.asMap().entries.map((entry) {
          final index = entry.key;
          final subCategory = entry.value;
          final isSelected = index == selectedSubIndex;

          return Padding(
            padding: const EdgeInsets.only(right: 12),
            child: ChoiceChip(
              label: Text(subCategory.title),
              selected: isSelected,
              onSelected: (selected) {
                if (selected) onSubIndexChanged(index);
              },
            ),
          );
        }).toList(),
      ),
    );
  }

  Widget _buildContentGrid(SubCategory subCategory) {
    return GridView.builder(
      gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 3,
        crossAxisSpacing: 16,
        mainAxisSpacing: 16,
        childAspectRatio: 1.2,
      ),
      itemCount: subCategory.items.length,
      itemBuilder: (context, index) {
        return _buildItemCard(context, subCategory.items[index], index);
      },
    );
  }

  Widget _buildItemCard(BuildContext context, DetailItem item, int index) {
    return Card(
      elevation: 4,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(12),
      ),
      child: InkWell(
        borderRadius: BorderRadius.circular(12),
        onTap: () {
          onDetailIndexChanged(index);
          _navigateToDetailPage(context, item);
        },
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Icon(Icons.description, color: Colors.blue, size: 32),
              const SizedBox(height: 8),
              Text(
                item.title,
                style: const TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.w500,
                ),
              ),
              const SizedBox(height: 4),
              Text(
                item.description,
                style: TextStyle(
                  fontSize: 12,
                  color: Colors.grey.shade600,
                ),
              ),
              const Spacer(),
              if (item.price > 0)
                Text(
                  '¥${item.price}',
                  style: const TextStyle(
                    fontSize: 14,
                    fontWeight: FontWeight.bold,
                    color: Colors.green,
                  ),
                ),
            ],
          ),
        ),
      ),
    );
  }

  void _navigateToDetailPage(BuildContext context, DetailItem item) {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => ItemDetailPage(item: item),
      ),
    );
  }
}

class ItemDetailPage extends StatelessWidget {
  final DetailItem item;

  const ItemDetailPage({super.key, required this.item});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(item.title),
        backgroundColor: Colors.transparent,
        elevation: 0,
        leading: IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () => Navigator.pop(context),
        ),
      ),
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            _buildDetailHeader(),
            const SizedBox(height: 24),
            _buildDetailContent(),
            const SizedBox(height: 24),
            _buildActionButtons(),
          ],
        ),
      ),
    );
  }

  Widget _buildDetailHeader() {
    return Row(
      children: [
        Container(
          width: 60,
          height: 60,
          decoration: BoxDecoration(
            color: Colors.blue.shade100,
            borderRadius: BorderRadius.circular(12),
          ),
          child: Icon(Icons.description, color: Colors.blue, size: 32),
        ),
        const SizedBox(width: 16),
        Expanded(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                item.title,
                style: const TextStyle(
                  fontSize: 24,
                  fontWeight: FontWeight.bold,
                ),
              ),
              Text(
                item.description,
                style: TextStyle(
                  fontSize: 16,
                  color: Colors.grey.shade600,
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }

  Widget _buildDetailContent() {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(20),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text(
              '详细信息',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 16),
            _buildInfoRow('产品名称', item.title),
            _buildInfoRow('产品描述', item.description),
            if (item.price > 0) _buildInfoRow('价格', '¥${item.price}'),
            const SizedBox(height: 20),
            const Text(
              '操作说明',
              style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
            ),
            const SizedBox(height: 12),
            Text(
              '在这里可以执行相关的操作,如编辑、删除、查看历史记录等。',
              style: TextStyle(color: Colors.grey.shade600),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildInfoRow(String label, String value) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 8),
      child: Row(
        children: [
          SizedBox(
            width: 80,
            child: Text(
              '$label:',
              style: TextStyle(
                fontWeight: FontWeight.w500,
                color: Colors.grey.shade700,
              ),
            ),
          ),
          const SizedBox(width: 12),
          Expanded(
            child: Text(
              value,
              style: const TextStyle(fontSize: 14),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildActionButtons() {
    return Row(
      children: [
        Expanded(
          child: ElevatedButton.icon(
            icon: const Icon(Icons.edit),
            label: const Text('编辑信息'),
            onPressed: () {},
          ),
        ),
        const SizedBox(width: 12),
        Expanded(
          child: OutlinedButton.icon(
            icon: const Icon(Icons.delete),
            label: const Text('删除'),
            onPressed: () {},
          ),
        ),
      ],
    );
  }
}
相关推荐
csj503 小时前
前端基础之《React(2)—webpack简介-使用Babel》
前端·react
刘新明19894 小时前
算法还原案例4-OLLVM_MD5
开发语言·前端·javascript·1024程序员节
言德斐5 小时前
Python Web框架深度对比:Django vs Flask vs FastAPI(含优缺点与选型策略)
前端·python·django
疯狂的沙粒5 小时前
前端开发【工具函数】基于dayjs 封装的DateUtils工具函数,可以直接拿着使用
前端·javascript·vue.js·1024程序员节
jingling5555 小时前
CSS进阶 | 不用一行JS!用纯CSS打造会动的现代化单页应用(3D翻转卡片)
前端·javascript·css
温宇飞6 小时前
浏览器路由系统的一种实践
前端
sunly_6 小时前
Flutter:启动动画Lottie
flutter
老前端的功夫7 小时前
Vue 插槽深度解析:从基础到高级架构设计
前端
pre_lee7 小时前
vue2响应式原理
前端