为了添加购物车和数量选择,需要在 _buildProductDetail 方法里面添加一个 Column,里面包含一个 Row 和一个 ElevatedButtonRow 包含数量选择和添加到购物车按钮,ElevatedButton 用来显示购物车商品数量和跳转到购物车页面。代码如下:

Widget _buildProductDetail(Product product) {
  int quantity = 1;
  return SingleChildScrollView(
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        CachedNetworkImage(
          imageUrl: product.imageUrl,
          fit: BoxFit.cover,
          errorWidget: (context, url, error) => Icon(Icons.error),
        ),
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                product.name,
                style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
              ),
              SizedBox(height: 8),
              Text(
                '价格: ¥${product.price.toStringAsFixed(2)}',
                style: TextStyle(fontSize: 18),
              ),
              SizedBox(height: 8),
              Text(
                '品牌: ${product.brand}',
                style: TextStyle(fontSize: 18),
              ),
              SizedBox(height: 8),
              Text(
                '描述: ${product.description}',
                style: TextStyle(fontSize: 18),
              ),
              SizedBox(height: 16),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Row(
                    children: [
                      IconButton(
                        icon: Icon(Icons.remove),
                        onPressed: () {
                          setState(() {
                            quantity = quantity > 1 ? quantity - 1 : 1;
                          });
                        },
                      ),
                      Text(
                        quantity.toString(),
                        style: TextStyle(fontSize: 18),
                      ),
                      IconButton(
                        icon: Icon(Icons.add),
                        onPressed: () {
                          setState(() {
                            quantity++;
                          });
                        },
                      ),
                    ],
                  ),
                  ElevatedButton(
                    onPressed: () async {
                      String url =
                          'http://book.musecloud.tech/addcart?productId=${product.id}&quantity=$quantity';
                      Response response = await _dio.get(url);
                      if (response.data == 'success') {
                        ScaffoldMessenger.of(context).showSnackBar(
                          SnackBar(
                            content: Text('添加到购物车成功'),
                            duration: Duration(seconds: 2),
                          ),
                        );
                      } else {
                        ScaffoldMessenger.of(context).showSnackBar(
                          SnackBar(
                            content: Text('添加到购物车失败,请稍后重试'),
                            duration: Duration(seconds: 2),
                          ),
                        );
                      }
                    },
                    child: Text('添加到购物车'),
                  ),
                ],
              ),
              SizedBox(height: 16),
              ElevatedButton(
                onPressed: () {
                  // TODO: 跳转到购物车页面
                },
                child: FutureBuilder<List<dynamic>>(
                  future: ApiService.getShoppingCart(),
                  builder: (context, snapshot) {
                    if (snapshot.hasData) {
                      int count = snapshot.data![1].length;
                      return Row(
                        children: [
                          Icon(Icons.shopping_cart),
                          SizedBox(width: 8),
                          Text('购物车($count)'),
                        ],
                      );
                    } else {
                      return Row(
                        children: [
                          Icon(Icons.shopping_cart),
                          SizedBox(width: 8),
                          Text('购物车'),
                        ],
                      );
                    }
                  },
                ),
              ),
            ],
          ),
        ),
      ],
    ),
  );
}

购物车展示的部分可以用一个 BottomSheet 实现,长按按钮展示,代码如下:

GestureDetector(
  onLongPress: () {
    showModalBottomSheet(
      context: context,
      builder: (context) {
        return FutureBuilder<List<dynamic>>(
          future: ApiService.getShoppingCart(),
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              List<dynamic> data = snapshot.data!;  
              List<dynamic> items = data[1];
              double totalPrice = data[2];
              return Container(
                height: 300,
                child: Column(
                  children: [
                    Expanded(
                      child: ListView.builder(
                        itemCount: items.length,
                        itemBuilder: (context, index) {
                          Product product = 
                              Product.fromJson(items[index]['product']);
                          int quantity = items[index]['quantity'];
                          return ListTile(
                            leading: CachedNetworkImage(
                              imageUrl: product.imageUrl,
                              width: 50,
                              height: 50,
                              fit: BoxFit.cover,
                              errorWidget: (context, url, error) => 
                                  Icon(Icons.error),
                            ),
                            title: Text(product.name),
                            subtitle: Text('¥${product.price} x $quantity'),
                          );
                        },
                      ),
                    ),
                    SizedBox(height: 16),
                    Text(
                      '总价: ¥${totalPrice.toStringAsFixed(2)}',
                      style: TextStyle(fontSize: 18),
                    ),
                    SizedBox(height: 16),
                    ElevatedButton(
                      onPressed: () {
                        // TODO: 跳转到结算页面
                      },
                      child: Text('结算'),
                    ),
                  ],
                ),
              );
            } else {
              return Center(
                child: CircularProgressIndicator(),
              );
            }
          },
        );
      },
    );
  },
  child: ElevatedButton(
    onPressed: () async {
      String url =
          'http://book.musecloud.tech/addcart?productId=${product.id}&quantity=$quantity';
      Response response = await _dio.get(url);
      if (response.data == 'success') {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('添加到购物车成功'),
            duration: Duration(seconds: 2),
          ),
        );
      } else {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('添加到购物车失败,请稍后重试'),
            duration: Duration(seconds: 2),
          ),
        );
      }
    },
    child: Text('添加到购物车'),
  ),
),

最后是对应的 model 和 api_service 代码,其中 getShoppingCart 方法返回的数据结构是一个 List,包含购物车所有商品信息、每个商品的信息和总价格:

class Product {
  int id;
  String name;
  String imageUrl;
  double price;
  String description;
  String brand;

  Product({
    required this.id,
    required this.name,
    required this.imageUrl,
    required this.price,
    required this.description,
    required this.brand,
  });

  factory Product.fromJson(Map<String, dynamic> json) {
    return Product(
      id: json['id'],
      name: json['name'],
      imageUrl: json['imageUrl'],
      price: json['price'].toDouble(),
      description: json['description'],
      brand: json['brand'],
    );
  }
}

class ApiService {
  static final String baseUrl = "http://book.musecloud.tech";
  static Dio _dio = Dio();

  // 获取产品列表
  static Future<List<Product>> getProductList({
    required int page,
    required int limit,
  }) async {
    try {
      Response response = await _dio.get(
        '$baseUrl/getproductlist',
        queryParameters: {
          'page': page,
          'limit': limit,
          'category': '',
          'keyword': '',
          'minprice': '',
          'maxprice': '',
          'origin': '',
          'brand': '',
          'supplier': '',
          'isActive': '',
          'isDeleted': '',
        },
      );
      List<dynamic> jsonData = jsonDecode(response.data);
      List<Product> products = 
          jsonData.map((json) => Product.fromJson(json)).toList();
      return products;
    } catch (e) {
      throw e;
    }
  }

  // 获取产品详情
  static Future<Product> getProductDetail(int id) async {
    try {
      Response response = await _dio.get('$baseUrl/getproductdetail?id=$id');
      dynamic jsonData = jsonDecode(response.data);
      Product product = Product.fromJson(jsonData);
      return product;
    } catch (e) {
      throw e;
    }
  }

  // 获取购物车信息
  static Future<List<dynamic>> getShoppingCart() async {
    try {
      Response response = await _dio.get('$baseUrl/getshoppingcart');
      dynamic jsonData = jsonDecode(response.data);
      return jsonData;
    } catch (e) {
      throw e;
    }
  }
}

Flutter 商城商品详情页添加购物车和数量选择功能

原文地址: https://www.cveoy.top/t/topic/oiev 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录