view.dart 7.3 KB
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:wow_english/common/extension/string_extension.dart';
import 'package:wow_english/models/product_entity.dart';

import '../../common/core/assets_const.dart';
import '../../common/widgets/we_app_bar.dart';
import '../../utils/image_util.dart';
import '../user/bloc/user_bloc.dart';
import 'bloc.dart';
import 'event.dart';
import 'state.dart';

Widget buildRadioOption({
  required int value,
  required ImageProvider icon,
  required String text,
  required bool isSelected,
  required ValueChanged onSelect,
}) {
  return GestureDetector(
    onTap: () {
      onSelect(value);
    },
    child: Row(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        Image(image: icon, width: 25.0.w, height: 25.0.h, fit: BoxFit.contain),
        const SizedBox(width: 10.0),
        Expanded(
          child: Text(
            text,
            style: TextStyle(color: const Color(0xFF333333), fontSize: 12.5.sp),
          ),
        ),
        Image(
          image: isSelected
              ? AssetImage('checked'.assetPng)
              : AssetImage('unchecked'.assetPng),
          width: 22.0.w,
          height: 22.0.h,
        ),
      ],
    ),
  );
}

class ShoppingPage extends StatelessWidget {
  const ShoppingPage({super.key, this.productEntity});

  final ProductEntity? productEntity;

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (BuildContext context) =>
          ShoppingBloc(productEntity)..add(InitEvent()),
      child: _ShoppingView(),
    );
  }
}

class _ShoppingView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final bloc = BlocProvider.of<ShoppingBloc>(context);
    final userBloc = BlocProvider.of<UserBloc>(context);
    return BlocListener<ShoppingBloc, ShoppingState>(
      listener: (context, state) {
        if (state is PaySuccessState) {
          userBloc.add(PayStateChangeEvent());
          Navigator.pop(context);
        }
      },
      child: Scaffold(
        appBar: WEAppBar(
          //标题传进来的
          titleText: bloc.productData?.name ?? '',
        ),
        body: Container(
          margin: const EdgeInsets.only(left: 80.0, top: 28.0, right: 56.0),
          child: Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Container(
                width: 210.w, // 图片宽度
                height: 210.w, // 图片高度
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(5.w),
                  // 圆角为5
                  border:
                      Border.all(width: 1.w, color: const Color(0xFF333333)),
                  // 边框宽度为1
                  // 使用ClipRRect圆角会有间隙,ClipRRect在裁剪时可能会导致圆角部分的边框显示不完整。
                  image: DecorationImage(
                    image: NetworkImage(bloc.productData?.detailPicUrl ?? ''),
                    // 图片地址
                    fit: BoxFit.cover, // 图片填充方式
                  ),
                ),
              ),
              const SizedBox(width: 35.5),
              Expanded(child: _paymentWidget())
            ],
          ),
        ),
      ),
    );
  }
}

Widget _paymentWidget() => BlocBuilder<ShoppingBloc, ShoppingState>(
      builder: (context, state) {
        final bloc = BlocProvider.of<ShoppingBloc>(context);
        return Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            RichText(
              text: TextSpan(children: [
                TextSpan(
                    text: '套餐价格:',
                    style: TextStyle(
                        color: const Color(0xFF333333), fontSize: 16.5.sp)),
                TextSpan(
                    text: '¥${bloc.productData?.price ?? ''}',
                    style: TextStyle(
                        color: const Color(0xFFE5262A), fontSize: 16.5.sp)),
              ]),
            ),
            const SizedBox(height: 14.5),
            Text(
              '套餐名称:${bloc.productData?.name}',
              style: TextStyle(color: const Color(0xFF333333), fontSize: 16.sp),
              maxLines: 2,
            ),
            const SizedBox(height: 14.5),
            Container(
              padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 10.h),
              decoration: BoxDecoration(
                  image: DecorationImage(
                      image: ImageUtil.getImageProviderOnDefault(
                          AssetsConst.bgUserInformationText),
                      fit: BoxFit.fill)),
              child: const Text('支付方式选择',
                  style: TextStyle(
                      color: Color(0xFF333333),
                      fontSize: 12.5,
                      fontFamily: 'PingFangSC-Regular')),
            ),
            const SizedBox(height: 18.0),
            buildRadioOption(
              value: PaymentChannel.wechatPay.payChannelType,
              icon: AssetImage('weixin'.assetPng),
              text: PaymentChannel.wechatPay.payChannelName,
              isSelected: bloc.curPaymentChannel.payChannelType ==
                  PaymentChannel.wechatPay.payChannelType,
              onSelect: (newValue) {
                bloc.add(ChangePaymentChannelEvent(PaymentChannel.wechatPay));
              },
            ),
            const SizedBox(height: 15.0),
            buildRadioOption(
              value: PaymentChannel.aliPay.payChannelType,
              icon: AssetImage('zhifubao'.assetPng),
              text: PaymentChannel.aliPay.payChannelName,
              isSelected: bloc.curPaymentChannel.payChannelType ==
                  PaymentChannel.aliPay.payChannelType,
              onSelect: (newValue) {
                bloc.add(ChangePaymentChannelEvent(PaymentChannel.aliPay));
              },
            ),
            const SizedBox(height: 20.0),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                RichText(
                  text: TextSpan(children: [
                    const TextSpan(
                        text: '需支付:',
                        style: TextStyle(
                            color: Color(0xFF333333),
                            fontSize: 12.5,
                            fontFamily: 'PingFangSC-Regular')),
                    TextSpan(
                        text: '¥${bloc.productData?.price ?? ''}',
                        style: TextStyle(
                            color: const Color(0xFFE7383B),
                            fontSize: 41.sp,
                            fontFamily: 'PingFangSC-Regular')),
                  ]),
                ),
                // 确认支付按钮
                GestureDetector(
                  onTap: () {
                    bloc.add(
                        DoPayEvent(bloc.productData, bloc.curPaymentChannel));
                  },
                  child: Image(
                    width: 105.w,
                    height: 45.h,
                    image: AssetImage('btn_pay'.assetPng),
                  ),
                )
              ],
            ),
          ],
        );
      },
    );