提交 8872e6ad authored 作者: maodou's avatar maodou

Merge remote-tracking branch 'origin/test' into test

# Conflicts: # lib/apis/mine.dart # lib/models/index.dart # lib/utils/styles.dart
...@@ -4,5 +4,5 @@ keyPassword=123456 ...@@ -4,5 +4,5 @@ keyPassword=123456
keyAlias=zijing keyAlias=zijing
#storeFile=/Users/apple/zijiing_key.jks storeFile=/Users/apple/zijiing_key.jks
storeFile=zijiing_key.jks #storeFile=zijiing_key.jks
\ No newline at end of file \ No newline at end of file
...@@ -477,6 +477,7 @@ ...@@ -477,6 +477,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = MYN43C5WGE;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "紫荆数智学堂"; INFOPLIST_KEY_CFBundleDisplayName = "紫荆数智学堂";
...@@ -644,6 +645,7 @@ ...@@ -644,6 +645,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = MYN43C5WGE;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "紫荆数智学堂"; INFOPLIST_KEY_CFBundleDisplayName = "紫荆数智学堂";
...@@ -664,6 +666,7 @@ ...@@ -664,6 +666,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = MYN43C5WGE;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "紫荆数智学堂"; INFOPLIST_KEY_CFBundleDisplayName = "紫荆数智学堂";
......
...@@ -163,4 +163,29 @@ abstract class CommonAPI { ...@@ -163,4 +163,29 @@ abstract class CommonAPI {
return result.data['filesUrl']; return result.data['filesUrl'];
} }
/// 11、创建订单
///
static Future <PayOrderModel> createOrder({
required String bookIdsList,
required String totalPrice,
required String couponRecId,
required String integral,
required String type
}) async {
final result = await HttpService.to.post(
'/v1/orders/Orders/createOrders',
params: {
'book_ids_list':bookIdsList,
'total_price':totalPrice,
'coupon_rec_id':couponRecId,
'integral':integral,
'type':type,
},
);
if (result.data is! Map) return PayOrderModel();
return PayOrderModel.fromJson(result.data);
}
} }
\ No newline at end of file
...@@ -64,7 +64,8 @@ abstract class LibraryAPI { ...@@ -64,7 +64,8 @@ abstract class LibraryAPI {
final result = await HttpService.to.post( final result = await HttpService.to.post(
'/v1/book/category/getBookList', '/v1/book/category/getBookList',
params: params params: params,
showLoading: true
); );
if (result.data is! Map && result.data['list'] is! List) return []; if (result.data is! Map && result.data['list'] is! List) return [];
return List.generate(result.data['list'].length, (index){ return List.generate(result.data['list'].length, (index){
...@@ -125,5 +126,20 @@ abstract class LibraryAPI { ...@@ -125,5 +126,20 @@ abstract class LibraryAPI {
return BookDetailModel.fromJson(result.data); return BookDetailModel.fromJson(result.data);
} }
/// 6、学习报告
///
static Future <ReportModel> report({
required String bookId
}) async {
final result = await HttpService.to.post(
'/v1/members/Information/myStudyReport',
params: {
'book_id':bookId
},
);
if (result.data is! Map) return ReportModel();
return ReportModel.fromJson(result.data);
}
} }
\ No newline at end of file
...@@ -330,4 +330,22 @@ abstract class MineAPI { ...@@ -330,4 +330,22 @@ abstract class MineAPI {
return OrderListModel.fromJson(result.data['list'][index]); return OrderListModel.fromJson(result.data['list'][index]);
}); });
} }
/// 19、紫荆币充值列表
///
static Future<List<CoinModel>> coinsRechargeList(
{
required String type,
}) async {
final result = await HttpService.to.post(
'/v1/orders/Orders/getRechargeConfig',
params: {
'config_type': type,
},
);
if (result.data is! Map && result.data['list'] is! List) return [];
return List.generate(result.data['list'].length, (index) {
return CoinModel.fromJson(result.data['list'][index]);
});
}
} }
...@@ -54,6 +54,60 @@ abstract class ShopAPI { ...@@ -54,6 +54,60 @@ abstract class ShopAPI {
}); });
} }
/// 4、获取使用积分
///
static Future <CreditPointModel> creditPoints({
required String price,
}) async {
final result = await HttpService.to.post(
'/v1/coupon/Coupon/getIntegral',
params: {
'price': price,
},
);
if (result.data is! Map ) return CreditPointModel();
return CreditPointModel.fromJson(result.data);
}
/// 5、优惠券和积分是否展示
///
static Future <ShowModel> show() async {
final result = await HttpService.to.post(
'/v1/orders/Orders/getSetting',
params: {},
);
if (result.data is! Map ) return ShowModel();
return ShowModel.fromJson(result.data);
}
/// 6、 支付时选的优惠券列表
static Future<CouponListModel> coupon({
int page = 1,
int limit = 10,
required String type,
required String price
}) async {
final result = await HttpService.to.post(
'/v1/coupon/Coupon/getCouponAll',
params: {'page': page, 'page_size': limit, 'type': type,'price':price},
);
if (result.data is! Map ) return CouponListModel();
return CouponListModel.fromJson(result.data);
}
/// 7、获取优惠券可使用和不可使用数量
static Future<CouponNumModel> couponNum({
required String price
}) async {
final result = await HttpService.to.post(
'/v1/coupon/Coupon/getCouponNum',
params: {
'price':price
},
);
if (result.data is! Map ) return CouponNumModel();
return CouponNumModel.fromJson(result.data);
}
} }
\ No newline at end of file
...@@ -52,9 +52,10 @@ class MyApp extends StatelessWidget { ...@@ -52,9 +52,10 @@ class MyApp extends StatelessWidget {
behavior: _NoShadowScrollBehavior(), behavior: _NoShadowScrollBehavior(),
child: OKToast( child: OKToast(
radius: 8.0, radius: 8.0,
backgroundColor: AppTheme.primary, backgroundColor: const Color(0xFF000000).withOpacity(0.2),
textPadding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 10.0), textPadding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 10.0),
position: ToastPosition.bottom, position: ToastPosition.bottom,
// textStyle: ,
child: child ?? const Material(), child: child ?? const Material(),
), ),
); );
......
...@@ -12,4 +12,5 @@ part 'msg.dart'; ...@@ -12,4 +12,5 @@ part 'msg.dart';
part 'study_history.dart'; part 'study_history.dart';
part 'library.dart'; part 'library.dart';
part 'mine.dart'; part 'mine.dart';
part 'order.dart'; part 'order.dart';
\ No newline at end of file part 'shop.dart';
\ No newline at end of file
...@@ -5,14 +5,17 @@ class CategoryModel { ...@@ -5,14 +5,17 @@ class CategoryModel {
CategoryModel({ CategoryModel({
this.categoryId, this.categoryId,
this.name, this.name,
this.selected = false,
}); });
CategoryModel.fromJson(dynamic json) { CategoryModel.fromJson(dynamic json) {
categoryId = json['category_id']; categoryId = json['category_id'];
name = json['name']; name = json['name'];
selected = false;
} }
num? categoryId; num? categoryId;
String? name; String? name;
late bool selected;
CategoryModel copyWith({ num? categoryId, CategoryModel copyWith({ num? categoryId,
String? name, String? name,
}) => CategoryModel( categoryId: categoryId ?? this.categoryId, }) => CategoryModel( categoryId: categoryId ?? this.categoryId,
...@@ -346,17 +349,116 @@ class BookDetailModel { ...@@ -346,17 +349,116 @@ class BookDetailModel {
} }
/// 删选模型
class FilterModel { class FilterModel {
FilterModel({ FilterModel({
required this.id, this.id,
required this.name, this.name,
this.selected = false this.selected = false
}); });
String id; String? id;
String name; String? name;
late bool selected = false; late bool selected = false;
} }
/// 学习报告模型
class ReportModel {
ReportModel({
this.bookName,
this.authors,
this.img,
this.progress,
this.readSecond,
this.maxSecond,
this.lastChapter,
this.commentPostNums,
this.commentReplyNums,
this.lineNums,
this.colorNums,
this.noteNums,
this.questionAllNums,
this.questionAccuracy,});
ReportModel.fromJson(dynamic json) {
bookName = json['book_name'];
authors = json['authors'];
img = json['img'];
progress = json['progress'];
readSecond = json['read_second'];
maxSecond = json['max_second'];
lastChapter = json['last_chapter'];
commentPostNums = json['comment_post_nums'];
commentReplyNums = json['comment_reply_nums'];
lineNums = json['line_nums'];
colorNums = json['color_nums'];
noteNums = json['note_nums'];
questionAllNums = json['question_all_nums'];
questionAccuracy = json['question_accuracy'];
}
String? bookName;
String? authors;
String? img;
String? progress;
String? readSecond;
num? maxSecond;
String? lastChapter;
num? commentPostNums;
num? commentReplyNums;
num? lineNums;
num? colorNums;
num? noteNums;
num? questionAllNums;
String? questionAccuracy;
ReportModel copyWith({ String? bookName,
String? authors,
String? img,
String? progress,
String? readSecond,
num? maxSecond,
String? lastChapter,
num? commentPostNums,
num? commentReplyNums,
num? lineNums,
num? colorNums,
num? noteNums,
num? questionAllNums,
String? questionAccuracy,
}) => ReportModel( bookName: bookName ?? this.bookName,
authors: authors ?? this.authors,
img: img ?? this.img,
progress: progress ?? this.progress,
readSecond: readSecond ?? this.readSecond,
maxSecond: maxSecond ?? this.maxSecond,
lastChapter: lastChapter ?? this.lastChapter,
commentPostNums: commentPostNums ?? this.commentPostNums,
commentReplyNums: commentReplyNums ?? this.commentReplyNums,
lineNums: lineNums ?? this.lineNums,
colorNums: colorNums ?? this.colorNums,
noteNums: noteNums ?? this.noteNums,
questionAllNums: questionAllNums ?? this.questionAllNums,
questionAccuracy: questionAccuracy ?? this.questionAccuracy,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['book_name'] = bookName;
map['authors'] = authors;
map['img'] = img;
map['progress'] = progress;
map['read_second'] = readSecond;
map['max_second'] = maxSecond;
map['last_chapter'] = lastChapter;
map['comment_post_nums'] = commentPostNums;
map['comment_reply_nums'] = commentReplyNums;
map['line_nums'] = lineNums;
map['color_nums'] = colorNums;
map['note_nums'] = noteNums;
map['question_all_nums'] = questionAllNums;
map['question_accuracy'] = questionAccuracy;
return map;
}
}
...@@ -77,6 +77,7 @@ class CouponModel { ...@@ -77,6 +77,7 @@ class CouponModel {
this.couponName, this.couponName,
this.normPrice, this.normPrice,
this.reducedPrice, this.reducedPrice,
this.type
}); });
CouponModel.fromJson(dynamic json) { CouponModel.fromJson(dynamic json) {
...@@ -96,6 +97,7 @@ class CouponModel { ...@@ -96,6 +97,7 @@ class CouponModel {
String? couponName; String? couponName;
num? normPrice; num? normPrice;
String? reducedPrice; String? reducedPrice;
num? type;
CouponModel copyWith({ CouponModel copyWith({
num? couponRecId, num? couponRecId,
...@@ -119,7 +121,7 @@ class CouponModel { ...@@ -119,7 +121,7 @@ class CouponModel {
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final map = <String, dynamic>{}; final map = <String, dynamic>{};
map['coupon_rec_id'] = couponRecId; map['coupon_rec_id'] = couponRecId;
map['end_time'] = endTime; // map['end_time'] = endTime;
map['coupon_id'] = couponId; map['coupon_id'] = couponId;
map['use_status'] = useStatus; map['use_status'] = useStatus;
map['coupon_name'] = couponName; map['coupon_name'] = couponName;
...@@ -612,3 +614,51 @@ class HelpCenterContentModel { ...@@ -612,3 +614,51 @@ class HelpCenterContentModel {
return map; return map;
} }
} }
/// 紫荆币模型
class CoinModel {
CoinModel({
this.beanName,
this.beanValue,
this.priceName,
this.priceValue,
this.identifying,
this.selected = false,
});
CoinModel.fromJson(dynamic json) {
beanName = json['bean_name'];
beanValue = json['bean_value'];
priceName = json['price_name'];
priceValue = json['price_value'];
identifying = json['identifying'];
selected = false;
}
String? beanName;
String? beanValue;
String? priceName;
String? priceValue;
String? identifying;
late bool selected;
CoinModel copyWith({ String? beanName,
String? beanValue,
String? priceName,
String? priceValue,
String? identifying,
}) => CoinModel( beanName: beanName ?? this.beanName,
beanValue: beanValue ?? this.beanValue,
priceName: priceName ?? this.priceName,
priceValue: priceValue ?? this.priceValue,
identifying: identifying ?? this.identifying,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['bean_name'] = beanName;
map['bean_value'] = beanValue;
map['price_name'] = priceName;
map['price_value'] = priceValue;
map['identifying'] = identifying;
return map;
}
}
...@@ -23,7 +23,7 @@ class MsgModel { ...@@ -23,7 +23,7 @@ class MsgModel {
title = json['title']; title = json['title'];
content = json['content']; content = json['content'];
status = json['status']; status = json['status'];
urlId = json['url_id']; urlId = json['url_id'] != null ? UrlIdModel.fromJson(json['url_id']) : null;
createTime = json['create_time']; createTime = json['create_time'];
} }
num? id; num? id;
...@@ -31,7 +31,7 @@ class MsgModel { ...@@ -31,7 +31,7 @@ class MsgModel {
String? title; String? title;
String? content; String? content;
num? status; num? status;
num? urlId; UrlIdModel? urlId;
String? createTime; String? createTime;
MsgModel copyWith({ MsgModel copyWith({
num? id, num? id,
...@@ -39,7 +39,7 @@ class MsgModel { ...@@ -39,7 +39,7 @@ class MsgModel {
String? title, String? title,
String? content, String? content,
num? status, num? status,
num? urlId, UrlIdModel? urlId,
String? createTime, String? createTime,
}) => MsgModel( }) => MsgModel(
id: id ?? this.id, id: id ?? this.id,
...@@ -57,9 +57,36 @@ class MsgModel { ...@@ -57,9 +57,36 @@ class MsgModel {
map['title'] = title; map['title'] = title;
map['content'] = content; map['content'] = content;
map['status'] = status; map['status'] = status;
map['url_id'] = urlId; if (urlId != null) {
map['url_id'] = urlId?.toJson();
}
map['create_time'] = createTime; map['create_time'] = createTime;
return map; return map;
} }
}
class UrlIdModel {
UrlIdModel({
this.bookId,
this.chapterId,});
UrlIdModel.fromJson(dynamic json) {
bookId = json['book_id'];
chapterId = json['chapter_id'];
}
num? bookId;
num? chapterId;
UrlIdModel copyWith({ num? bookId,
num? chapterId,
}) => UrlIdModel( bookId: bookId ?? this.bookId,
chapterId: chapterId ?? this.chapterId,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['book_id'] = bookId;
map['chapter_id'] = chapterId;
return map;
}
} }
\ No newline at end of file
part of models;
class PayModel { class PayModel {
PayModel({ PayModel({
required this.type, required this.type,
...@@ -12,4 +14,226 @@ class PayModel { ...@@ -12,4 +14,226 @@ class PayModel {
String icon; String icon;
bool selected; bool selected;
}
/// 可使用积分模型
class CreditPointModel {
CreditPointModel({
this.integral,
this.onePointDeductionAmount,
this.integralUseLimit,
this.integralSwitch,
this.deductibleAmount,
this.deductibleIntegral,});
CreditPointModel.fromJson(dynamic json) {
integral = json['integral'];
onePointDeductionAmount = json['one_point_deduction_amount'];
integralUseLimit = json['integral_use_limit'];
integralSwitch = json['integral_switch'];
deductibleAmount = json['deductible_amount'];
deductibleIntegral = json['deductible_integral'];
}
num? integral;
String? onePointDeductionAmount;
String? integralUseLimit;
String? integralSwitch;
String? deductibleAmount;
num? deductibleIntegral;
CreditPointModel copyWith({ num? integral,
String? onePointDeductionAmount,
String? integralUseLimit,
String? integralSwitch,
String? deductibleAmount,
num? deductibleIntegral,
}) => CreditPointModel( integral: integral ?? this.integral,
onePointDeductionAmount: onePointDeductionAmount ?? this.onePointDeductionAmount,
integralUseLimit: integralUseLimit ?? this.integralUseLimit,
integralSwitch: integralSwitch ?? this.integralSwitch,
deductibleAmount: deductibleAmount ?? this.deductibleAmount,
deductibleIntegral: deductibleIntegral ?? this.deductibleIntegral,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['integral'] = integral;
map['one_point_deduction_amount'] = onePointDeductionAmount;
map['integral_use_limit'] = integralUseLimit;
map['integral_switch'] = integralSwitch;
map['deductible_amount'] = deductibleAmount;
map['deductible_integral'] = deductibleIntegral;
return map;
}
}
/// 优惠券和 积分是否展示模型
class ShowModel {
ShowModel({
this.couponSwitch,
this.integralSwitch,
this.membersBean,
});
ShowModel.fromJson(dynamic json) {
couponSwitch = json['coupon_switch'];
integralSwitch = json['integral_switch'];
membersBean = json['members_bean'];
}
String? couponSwitch;
String? integralSwitch;
String? membersBean;
ShowModel copyWith({ String? couponSwitch,
String? integralSwitch,
String? membersBean,
}) => ShowModel( couponSwitch: couponSwitch ?? this.couponSwitch,
integralSwitch: integralSwitch ?? this.integralSwitch,
membersBean: membersBean ?? this.integralSwitch
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['coupon_switch'] = couponSwitch;
map['integral_switch'] = integralSwitch;
map['members_bean'] = membersBean;
return map;
}
}
class CouponListModel {
CouponListModel({
this.list,
this.total,});
CouponListModel.fromJson(dynamic json) {
if (json['list'] != null) {
list = [];
json['list'].forEach((v) {
list?.add(CouponModel.fromJson(v));
});
}
total = json['total'];
}
List<CouponModel>? list;
num? total;
CouponListModel copyWith({ List<CouponModel>? list,
num? total,
}) => CouponListModel( list: list ?? this.list,
total: total ?? this.total,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
if (list != null) {
map['list'] = list?.map((v) => v.toJson()).toList();
}
map['total'] = total;
return map;
}
}
/// 优惠券可使用和不可使用数量
class CouponNumModel {
CouponNumModel({
this.availableNum,
this.unavailableNum,});
CouponNumModel.fromJson(dynamic json) {
availableNum = json['available_num'];
unavailableNum = json['unavailable_num'];
}
num? availableNum;
num? unavailableNum;
CouponNumModel copyWith({ num? availableNum,
num? unavailableNum,
}) => CouponNumModel( availableNum: availableNum ?? this.availableNum,
unavailableNum: unavailableNum ?? this.unavailableNum,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['available_num'] = availableNum;
map['unavailable_num'] = unavailableNum;
return map;
}
}
/// 创建订单模型
class PayOrderModel {
PayOrderModel({
this.appid,
this.partnerid,
this.prepayid,
this.package,
this.noncestr,
this.timestamp,
this.sign,
this.ordersnum,
this.encryptionOrder,
this.code,
String? msg,
});
PayOrderModel.fromJson(dynamic json) {
appid = json['appid'];
partnerid = json['partnerid'];
prepayid = json['prepayid'];
package = json['package'];
noncestr = json['noncestr'];
timestamp = json['timestamp'];
sign = json['sign'];
ordersnum = json['ordersnum'];
encryptionOrder = json['encryption_order'];
code = json['code'];
msg = json['msg'];
}
String? appid;
String? partnerid;
String? prepayid;
String? package;
String? noncestr;
num? timestamp;
String? sign;
String? ordersnum;
String? encryptionOrder;
num? code;
String? msg;
PayOrderModel copyWith({ String? appid,
String? partnerid,
String? prepayid,
String? package,
String? noncestr,
num? timestamp,
String? sign,
String? ordersnum,
String? encryptionOrder,
num? code,
String? msg,
}) => PayOrderModel( appid: appid ?? this.appid,
partnerid: partnerid ?? this.partnerid,
prepayid: prepayid ?? this.prepayid,
package: package ?? this.package,
noncestr: noncestr ?? this.noncestr,
timestamp: timestamp ?? this.timestamp,
sign: sign ?? this.sign,
ordersnum: ordersnum ?? this.ordersnum,
encryptionOrder: encryptionOrder ?? this.encryptionOrder,
code: code ?? this.code,
msg: msg?? this.msg,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['appid'] = appid;
map['partnerid'] = partnerid;
map['prepayid'] = prepayid;
map['package'] = package;
map['noncestr'] = noncestr;
map['timestamp'] = timestamp;
map['sign'] = sign;
map['ordersnum'] = ordersnum;
map['encryption_order'] = encryptionOrder;
map['code'] = code;
map['msg'] = msg;
return map;
}
} }
\ No newline at end of file
...@@ -13,25 +13,34 @@ class _AdPageState extends State<AdPage> { ...@@ -13,25 +13,34 @@ class _AdPageState extends State<AdPage> {
return GetBuilder<AdController>( return GetBuilder<AdController>(
init: AdController(context), init: AdController(context),
builder:(controller) => Scaffold( builder:(controller) => Scaffold(
body: Center( body: Stack(
child: Column( fit: StackFit.expand,
mainAxisAlignment: MainAxisAlignment.center, children: [
children: [ Container(
Container( color: Colors.green,
height: 200.w, ),
width: 200.w, Positioned(
color: Colors.lime, top: 40.w,
), right: 20.w,
SizedBox(height: 20.w), child: GestureDetector(
Text( onTap: (){
'倒计时:${controller._countdown}', context.goNamed(Routes.main);
style: TextStyle( },
fontSize: 20.w child: Container(
padding: EdgeInsets.symmetric(horizontal: 12.0.w, vertical: 8.0.w),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.6),
borderRadius: BorderRadius.circular(8.0.w),
),
child: Text(
'跳过 ${controller._countdown} s',
style: const TextStyle(color: Colors.white),
),
), ),
), )
], )
), ],
), )
) )
); );
......
...@@ -33,7 +33,7 @@ class _BuildItemState extends State<BuildItem> { ...@@ -33,7 +33,7 @@ class _BuildItemState extends State<BuildItem> {
Row( Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Text(widget.model.name??'',style: TextStyle(fontSize: 14.w,color: widget.model.seen ==0? Colours.c3:Colours.c9,fontWeight: Fonts.medium,height: 1.4),), Text(widget.model.name??'',style: TextStyle(fontSize: 14.w,color: widget.model.seen ==0? Colours.c3:Colours.c9,fontWeight: Fonts.medium,height: 2),),
Gaps.hGaps5, Gaps.hGaps5,
widget.model.isReading == 1? Container( widget.model.isReading == 1? Container(
height: 17, height: 17,
...@@ -76,7 +76,7 @@ class _BuildItemState extends State<BuildItem> { ...@@ -76,7 +76,7 @@ class _BuildItemState extends State<BuildItem> {
return Container( return Container(
color: Colors.white, color: Colors.white,
padding: const EdgeInsets.only(left: 60), padding: const EdgeInsets.only(left: 60),
child: Text(model.name??'',style:TextStyle(fontSize: 12,color: model.seen ==0? Colours.c3:Colours.c9,height: 1.6),), child: Text(model.name??'',style:TextStyle(fontSize: 12,color: model.seen ==0? Colours.c3:Colours.c9,height: 2),),
); );
} }
} }
...@@ -39,6 +39,14 @@ class BookDetailController extends GetxController with GetSingleTickerProviderSt ...@@ -39,6 +39,14 @@ class BookDetailController extends GetxController with GetSingleTickerProviderSt
super.onClose(); super.onClose();
} }
/// 加入书架
void addCart(String bookId) async {
final result = await ShopAPI.addCart(bookId: bookId);
if(result){
Toast.show('添加购物车成功');
}
}
/// 获取目录信息 /// 获取目录信息
void _getChapters() async { void _getChapters() async {
chapters = await LibraryAPI.chapters(bookId: bookId); chapters = await LibraryAPI.chapters(bookId: bookId);
......
...@@ -98,7 +98,12 @@ class _BookDetailPageState extends State<BookDetailPage> with SingleTickerProvid ...@@ -98,7 +98,12 @@ class _BookDetailPageState extends State<BookDetailPage> with SingleTickerProvid
Expanded( Expanded(
child: GestureDetector( child: GestureDetector(
onTap: (){ onTap: (){
context.pushNamed(Routes.studyReport); if(controller.bookDetails.isHave ==1){
context.pushNamed(Routes.studyReport,queryParameters: {'book_id':widget.bookId});
}
else{
controller.addCart(widget.bookId);
}
}, },
child: Container( child: Container(
alignment: Alignment.center, alignment: Alignment.center,
...@@ -126,7 +131,22 @@ class _BookDetailPageState extends State<BookDetailPage> with SingleTickerProvid ...@@ -126,7 +131,22 @@ class _BookDetailPageState extends State<BookDetailPage> with SingleTickerProvid
/// 没有购买并且没有试读直接跳转 购买页 /// 没有购买并且没有试读直接跳转 购买页
bool noTryRead = true; bool noTryRead = true;
if(controller.bookDetails.isHave == 0 && noTryRead){ if(controller.bookDetails.isHave == 0 && noTryRead){
context.pushNamed(Routes.bookPay); List<CourseModel> buy = [];
CourseModel model= CourseModel(
bookId: controller.bookDetails.bookId,
price: controller.bookDetails.price,
vipPrice: controller.bookDetails.vipPrice,
img: controller.bookDetails.img,
bookName: controller.bookDetails.bookName,
cartId: 0,
status: 1,
selected: true
);
buy.add(model);
context.pushNamed(Routes.bookPay,extra: buy);
}
else {
context.pushNamed(Routes.web);
} }
}, },
child: Container( child: Container(
......
part of book_pay; part of book_pay;
class BookPayController extends GetxController { class BookPayController extends GetxController {
// 购物车选中的书籍列表
final List<CourseModel> buy; final List<CourseModel> buy;
BookPayController(this.buy); BookPayController({required this.buy});
// 积分模型
CreditPointModel creditPointModel = CreditPointModel(deductibleIntegral: 0);
// 是否展示优惠券和积分模型
ShowModel showModel = ShowModel();
// 是否使用积分
bool useCreditPoint = false;
// 优惠券可用不可用数量模型
CouponNumModel couponNumModel = CouponNumModel();
// 选择的优惠券模型
late CouponModel useCouponModel = CouponModel(couponId: 0,reducedPrice: '0.00',couponRecId: 0);
// 创建订单模型
late PayOrderModel payOrderModel;
// 支付方式 // 支付方式
List<PayModel> pays = Platform.isIOS ?[ List<PayModel> pays = Platform.isIOS ?[
...@@ -13,11 +27,42 @@ class BookPayController extends GetxController { ...@@ -13,11 +27,42 @@ class BookPayController extends GetxController {
PayModel(type: 3, name: '紫荆币', icon: 'assets/images/pay_coin.png', selected: false), PayModel(type: 3, name: '紫荆币', icon: 'assets/images/pay_coin.png', selected: false),
]; ];
// 时候展示底部视图
bool showDetail = false;
// 支付方式 // 优惠前的原始价钱
late double originalPrice = getOriginalPrice();
// late double finalPrice = 0.00;
Decimal finalPrice = Decimal.zero;
@override
void onReady() {
_getCreditPoints(price: originalPrice.toString());
_getShow();
computeFinalPrice();
_getCouponNumber();
super.onReady();
}
/// 使用优惠券
void setUseCoupon(CouponModel model){
useCouponModel = model;
print('使用优惠券。。。。。。。。。。。。。。。。');
computeFinalPrice();
}
/// 支付方式 默认第一个
late PayModel _payModel = pays.first; late PayModel _payModel = pays.first;
PayModel get payModel => _payModel; PayModel get payModel => _payModel;
/// 选择积分状态
void show(){
showDetail = !showDetail;
update();
}
/// 设置支付渠道
void setPayModel(PayModel payModel){ void setPayModel(PayModel payModel){
for (PayModel model in pays) { for (PayModel model in pays) {
if (model.type == payModel.type){ if (model.type == payModel.type){
...@@ -31,19 +76,114 @@ class BookPayController extends GetxController { ...@@ -31,19 +76,114 @@ class BookPayController extends GetxController {
update(); update();
} }
/// 是否使用积分
void setUse(){
useCreditPoint = !useCreditPoint;
// 计算
computeFinalPrice();
update();
}
/// 获取积分
void _getCreditPoints({
required String price
}) async {
creditPointModel = await ShopAPI.creditPoints(price: price);
update();
}
/// 是否展示优惠券 和积分使用 模型
void _getShow () async {
showModel = await ShopAPI.show();
update();
}
/// 获取优惠券可用数量与不可用数量模型
void _getCouponNumber() async{
couponNumModel = await ShopAPI.couponNum(price: originalPrice.toString());
update();
}
/// 获取优惠前的价钱
/// 总价钱
double getOriginalPrice(){
Decimal price = Decimal.zero;
for (CourseModel model in buy!) {
if (model.status == 1){
if (model.selected == true){
price = price + Decimal.parse(model.vipPrice??'0.00');
print('==============11111111111==================$price');
}
}
}
print('================================$price');
return price.toDouble();
}
/// 获取优惠后的价格
void computeFinalPrice(){
finalPrice = Decimal.parse(originalPrice.toString());
if (useCreditPoint){
finalPrice = finalPrice - Decimal.parse(creditPointModel.deductibleAmount??'0.00');
}
// 不等0的时候证明使用了 优惠券
if (useCouponModel.couponId !=0){
finalPrice = finalPrice - Decimal.parse(useCouponModel.reducedPrice??'0.00');
}
update();
}
/// 创建订单
void createOrder() async {
List<Map<String, dynamic>> bookIdsList = [];
for (CourseModel model in buy){
Map<String, dynamic> tempMap = {
'book_id': model.bookId,
'price': model.price,
'cart_id': model.cartId,
};
bookIdsList.add(tempMap);
}
// 书豆支付的话先判断书豆数量
if (finalPrice.toDouble() > double.parse(showModel.membersBean.toString())){
Toast.show('紫金币不足,请先充值紫荆币');
return;
}
final result = await CommonAPI.createOrder(
bookIdsList:jsonEncode(bookIdsList) ,
totalPrice: finalPrice.toString(),
couponRecId: useCouponModel.couponRecId.toString(),
integral: creditPointModel.deductibleIntegral.toString(),
type: payModel.type.toString()
);
payOrderModel = result;
// 微信
if(payModel.type == 1){
String orderNumber = payOrderModel.ordersnum.toString();
//TODO: 拿到订单编号进行微信支付操作
}
// 支付宝
else if(payModel.type == 2){
String orderNumber = payOrderModel.ordersnum.toString();
//TODO: 拿到订单编号进行支付宝支付操作
}
// 书豆
else if (payModel.type == 3){
if(payOrderModel.code == -1){
Toast.show('紫金币不足,请先充值紫荆币');
}
String orderNumber = payOrderModel.ordersnum.toString();
//TODO: 拿到订单编号进行后续操作
}
}
// /// 获取总价
// ///总价格
// double get allPrice{
// Decimal price = Decimal.zero;
// for (CourseModel model in buy) {
// if (model.status == 1){
// if (model.selected == true){
// price = price + Decimal.parse(model.vipPrice??'0.00');
// }
// }
// }
// return price.toDouble();
// }
} }
\ No newline at end of file
library book_pay; library book_pay;
import 'dart:convert';
import 'dart:core';
import 'package:decimal/decimal.dart'; import 'package:decimal/decimal.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_book/apis/index.dart';
import 'package:flutter_book/theme.dart'; import 'package:flutter_book/theme.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:flutter_slidable/flutter_slidable.dart';
...@@ -10,7 +14,6 @@ import 'package:get/get.dart'; ...@@ -10,7 +14,6 @@ import 'package:get/get.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import '../../models/index.dart'; import '../../models/index.dart';
import '../../models/shop.dart';
import '../../routes/index.dart'; import '../../routes/index.dart';
import '../../utils/index.dart'; import '../../utils/index.dart';
import '../../widgets/index.dart'; import '../../widgets/index.dart';
......
part of book_pay; part of book_pay;
class BuildPayCount extends StatelessWidget { class BuildPayCount extends StatelessWidget {
const BuildPayCount({Key? key}) : super(key: key); final void Function()? payTap;
final void Function()? showTap;
final BookPayController controller;
const BuildPayCount({
Key? key,
required this.payTap,
required this.showTap,
required this.controller
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return GetBuilder<BookPayController>(
padding: EdgeInsets.symmetric(horizontal: 15.w), init: BookPayController(buy: []),
height: 55.w, builder:(controller)=> Container(
color: Colors.white, padding: EdgeInsets.symmetric(horizontal: 15.w),
child: Row( height: 55.w,
mainAxisAlignment: MainAxisAlignment.spaceBetween, color: Colors.white,
crossAxisAlignment: CrossAxisAlignment.center, child: Row(
children: [ mainAxisAlignment: MainAxisAlignment.spaceBetween,
Row( crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Text('应付:',style: TextStyle(fontSize:14.w,color: Colours.c3 ,height: 1.1),), IgnorePointer(
Text('¥98.9',style: TextStyle(fontSize:15.w,color:AppTheme.primary,fontWeight: Fonts.medium ,height: 1.1),) ignoring: controller.showModel.integralSwitch =='0'&& controller.showModel.couponSwitch ==''?true:false,
], child: GestureDetector(
), onTap: showTap,
Container( child: Row(
decoration: BoxDecoration( crossAxisAlignment: CrossAxisAlignment.center,
borderRadius: BorderRadius.circular(15.w), children: [
color: AppTheme.primary Text('应付:',style: TextStyle(fontSize:14.w,color: Colours.c3 ,height: 1.1),),
Text('¥${controller.finalPrice}',style: TextStyle(fontSize:15.w,color:AppTheme.primary,fontWeight: Fonts.medium ,height: 1.1),),
controller.showModel.integralSwitch =='1'&& controller.showModel.couponSwitch =='1'?SizedBox(
// color: Colors.cyan,
width: 20.w,
height: 20.w,
child: Image.asset('assets/images/pay_up.png')
):const SizedBox()
],
),
),
), ),
padding: EdgeInsets.symmetric(horizontal:13.5.w,vertical: 8.w), GestureDetector(
child: Text('确认支付',style: TextStyle(fontSize: 14.w,fontWeight: Fonts.medium,color: Colors.white),), onTap: payTap,
) child: Container(
], decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.w),
color: AppTheme.primary
),
padding: EdgeInsets.symmetric(horizontal:13.5.w,vertical: 8.w),
child: Text('确认支付',style: TextStyle(fontSize: 14.w,fontWeight: Fonts.medium,color: Colors.white),),
),
)
],
),
), ),
); );
} }
......
...@@ -15,15 +15,15 @@ class BuildItem extends StatelessWidget { ...@@ -15,15 +15,15 @@ class BuildItem extends StatelessWidget {
padding: EdgeInsets.only(left: 15.w, top: 15.w,right: 10.w,bottom: 15.w), padding: EdgeInsets.only(left: 15.w, top: 15.w,right: 10.w,bottom: 15.w),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
boxShadow: const [ boxShadow: [
BoxShadow( BoxShadow(
color: Colours.cC7, color: Colours.cC7.withOpacity(0.5),
offset: Offset(0, 3), offset: Offset(3.w, 0.w),
blurRadius: 4, blurRadius: 4.w,
spreadRadius: 0, spreadRadius: 0,
), ),
], ],
borderRadius: BorderRadius.circular(8) borderRadius: BorderRadius.circular(8.w)
), ),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
...@@ -31,13 +31,13 @@ class BuildItem extends StatelessWidget { ...@@ -31,13 +31,13 @@ class BuildItem extends StatelessWidget {
Row( Row(
children: [ children: [
Container( Container(
width: 35, width: 35.w,
height: 35, height: 35.w,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.cyan, color: Colors.cyan,
borderRadius: BorderRadius.circular(17.5) borderRadius: BorderRadius.circular(17.5.w)
), ),
child: CustomImage.network(url: model.usersImg??''), child: CustomImage.network(url: model.usersImg??'',radius: 17.5.w,),
), ),
Gaps.hGaps10, Gaps.hGaps10,
Expanded( Expanded(
...@@ -47,9 +47,9 @@ class BuildItem extends StatelessWidget { ...@@ -47,9 +47,9 @@ class BuildItem extends StatelessWidget {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text(model.users??'',style: const TextStyle(fontSize: 12,height: 1.3,color: Colours.c9),), Text(model.users??'',style: TextStyle(fontSize: 12.w,height: 1.3,color: Colours.c9),),
// Spacer(), // Spacer(),
Text(model.createTime??'',style: const TextStyle(fontSize: 12,height: 1.3,color: Colours.c9),) Text(model.createTime??'',style: TextStyle(fontSize: 12.w,height: 1.3,color: Colours.c9),)
], ],
), ),
AbsorbPointer( AbsorbPointer(
...@@ -57,10 +57,10 @@ class BuildItem extends StatelessWidget { ...@@ -57,10 +57,10 @@ class BuildItem extends StatelessWidget {
child: CustomRating( child: CustomRating(
max: 5, max: 5,
score:model.rating!.toDouble() , score:model.rating!.toDouble() ,
star: const Star( star: Star(
progress: 7, progress: 7,
fillColor: AppTheme.primary, fillColor: AppTheme.primary,
size: 12, size: 12.w,
emptyColor: Colours.cE2, emptyColor: Colours.cE2,
), onRating: (double ) {}, ), onRating: (double ) {},
), ),
...@@ -71,7 +71,7 @@ class BuildItem extends StatelessWidget { ...@@ -71,7 +71,7 @@ class BuildItem extends StatelessWidget {
], ],
), ),
Gaps.vGaps15, Gaps.vGaps15,
Text(model.comments??'',style: const TextStyle(fontSize: 14,height: 1.5,color: Colours.c3),) Text(model.comments??'',style: TextStyle(fontSize: 14.w,height: 1.5,color: Colours.c3),)
], ],
), ),
), ),
......
...@@ -152,7 +152,7 @@ class BookshopController extends GetxController { ...@@ -152,7 +152,7 @@ class BookshopController extends GetxController {
); );
// 如果是刷新 清理数据 // 如果是刷新 清理数据
if (isRefresh) carts.clear(); if (isRefresh) carts.clear();
carts.addAll(_test()); // carts.addAll(_test());
carts.addAll(result); carts.addAll(result);
_page ++; _page ++;
_noMore = result.length < _limit; _noMore = result.length < _limit;
...@@ -186,9 +186,11 @@ class BookshopController extends GetxController { ...@@ -186,9 +186,11 @@ class BookshopController extends GetxController {
List<CourseModel> _test(){ List<CourseModel> _test(){
return [ return [
CourseModel(bookName: '哈1',bookId: 111,vipPrice: '12.33',authors: 'John',status: 1), CourseModel(bookName: '哈1',bookId: 111,vipPrice: '100.33',authors: 'John',status: 1),
CourseModel(bookName: '哈2',bookId: 123,vipPrice: '12.00',authors: 'json',status: 1), CourseModel(bookName: '哈2',bookId: 123,vipPrice: '12.00',authors: 'json',status: 1),
CourseModel(bookName: '哈3',bookId: 11,vipPrice: '12.43',authors: 'hash',status: 1), CourseModel(bookName: '哈3',bookId: 11,vipPrice: '12.43',authors: 'hash',status: 1),
CourseModel(bookName: '哈3',bookId: 11,vipPrice: '12.43',authors: 'hash',status: 1),
CourseModel(bookName: '哈3',bookId: 11,vipPrice: '12.43',authors: 'hash',status: 1),
]; ];
} }
......
part of change_pwd; part of change_pwd;
class ChangePwdController extends GetxController { class ChangePwdController extends GetxController {
final UserInfoModel userInfo;
ChangePwdController(this.userInfo);
// 新密码 // 新密码
final TextEditingController pwdInput = TextEditingController(); final TextEditingController pwdInput = TextEditingController();
// 确认密码 // 确认密码
...@@ -40,7 +41,14 @@ class ChangePwdController extends GetxController { ...@@ -40,7 +41,14 @@ class ChangePwdController extends GetxController {
} }
Future <bool> changePwd() async { Future <bool> changePwd() async {
final result = await MineAPI.changePwd(password: EncryptUtil.encodeMd5(EncryptUtil.encodeMd5(pwdInput.text)), rePassword: EncryptUtil.encodeMd5(EncryptUtil.encodeMd5(pwd2Input.text))); final result = await MineAPI.changePwd(
password: EncryptUtil.encodeMd5(EncryptUtil.encodeMd5(pwdInput.text)),
rePassword: EncryptUtil.encodeMd5(EncryptUtil.encodeMd5(pwd2Input.text))
);
if(result){
userInfo.password = EncryptUtil.encodeMd5(EncryptUtil.encodeMd5(pwdInput.text));
update();
}
return result; return result;
} }
......
...@@ -8,6 +8,7 @@ import 'package:flutter/material.dart'; ...@@ -8,6 +8,7 @@ import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import '../../apis/index.dart'; import '../../apis/index.dart';
import '../../models/index.dart';
import '../../routes/index.dart'; import '../../routes/index.dart';
import '../../widgets/index.dart'; import '../../widgets/index.dart';
......
part of change_pwd; part of change_pwd;
class ChangePwdPage extends StatefulWidget { class ChangePwdPage extends StatefulWidget {
final String type; final UserInfoModel userInfo;
const ChangePwdPage({ const ChangePwdPage({
Key? key , Key? key ,
required this.type, required this.userInfo,
}) : super(key: key); }) : super(key: key);
// const ResetPwdPage({Key? key}) : super(key: key); // const ResetPwdPage({Key? key}) : super(key: key);
...@@ -17,11 +17,11 @@ class _ChangePwdPageState extends State<ChangePwdPage> { ...@@ -17,11 +17,11 @@ class _ChangePwdPageState extends State<ChangePwdPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final currentContext = context; final currentContext = context;
return GetBuilder<ChangePwdController>( return GetBuilder<ChangePwdController>(
init: ChangePwdController(), init: ChangePwdController(widget.userInfo),
builder: (controller) =>Scaffold( builder: (controller) =>Scaffold(
appBar: AppBar( appBar: AppBar(
centerTitle: true, centerTitle: true,
title: Text(widget.type =='1'?'设置密码':'修改密码'), title: Text(widget.userInfo.password.toString().isEmpty?'设置密码':'修改密码'),
), ),
body: Container( body: Container(
margin: EdgeInsets.only(left: 10.w,top: 15.w,right: 10.w), margin: EdgeInsets.only(left: 10.w,top: 15.w,right: 10.w),
...@@ -117,7 +117,7 @@ class _ChangePwdPageState extends State<ChangePwdPage> { ...@@ -117,7 +117,7 @@ class _ChangePwdPageState extends State<ChangePwdPage> {
), ),
Gaps.vGaps40, Gaps.vGaps40,
CustomGradientButton( CustomGradientButton(
text: widget.type == '1'?'确认':'确认修改', text: widget.userInfo.password.toString().isEmpty ?'确认':'确认修改',
isEnabled: controller.enable, isEnabled: controller.enable,
onPressed: () async { onPressed: () async {
Tools.unfocus(); Tools.unfocus();
......
part of credit_points;
class CreditPointController extends GetxController {
final String price;
CreditPointController(this.price);
CreditPointModel creditPointModel = CreditPointModel();
bool use = false;
@override
void onReady() {
_getCreditPoints(price: price);
super.onReady();
}
void setUse(){
use = !use;
update();
}
void _getCreditPoints({
required String price
}) async {
creditPointModel = await ShopAPI.creditPoints(price: price);
update();
}
}
...@@ -6,6 +6,12 @@ import 'package:flutter/material.dart'; ...@@ -6,6 +6,12 @@ import 'package:flutter/material.dart';
import 'package:flutter_book/theme.dart'; import 'package:flutter_book/theme.dart';
import 'package:flutter_book/utils/index.dart'; import 'package:flutter_book/utils/index.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get_state_manager/get_state_manager.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
part 'view.dart'; import '../../apis/index.dart';
\ No newline at end of file import '../../models/index.dart';
import '../book_pay/index.dart';
part 'view.dart';
part 'controller.dart';
\ No newline at end of file
part of library;
class LibraryContentController extends GetxController {
final EasyRefreshController refreshController = EasyRefreshController(
controlFinishLoad: true,
controlFinishRefresh: true,
);
// 图书列表数据
List<CourseModel> books = [];
final int _limit = 20;
int _page = 1;
bool _noMore = false;
@override
void onClose() {
refreshController.dispose();
super.onClose();
}
/// 收藏 与 取消收藏
void love({
required String bookId,
required num isCollection
}) async {
if (isCollection == 0){
isCollection = 1;
}
else{
isCollection = 0;
}
bool result = await CommonAPI.love(bookId: bookId, love: isCollection.toString());
if (result) {
onRefresh();
}
}
/// 获取图书列表数据
Future<void> _getBooks([bool isRefresh = false]) async {
if (isRefresh) _page = 1;
// 网路请求
final result = await LibraryAPI.books(
page: _page,
limit: _limit, categoryId: '',
);
// 如果是刷新 清理数据
if (isRefresh) books.clear();
books.addAll(result);
_page ++;
_noMore = result.length < _limit;
update();
}
void onRefresh() async {
try {
await _getBooks(true);
refreshController.finishRefresh(IndicatorResult.success);
refreshController.resetFooter();
} catch (error) {
refreshController.finishRefresh(IndicatorResult.fail);
}
}
void onLoading() async {
if (_noMore) {
refreshController.finishLoad(IndicatorResult.noMore);
return;
}
try {
await _getBooks();
refreshController.finishLoad();
} catch (error) {
refreshController.finishLoad(IndicatorResult.fail);
}
}
}
\ No newline at end of file
...@@ -9,11 +9,39 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{ ...@@ -9,11 +9,39 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{
// 广告数组 // 广告数组
List<AdModel> ads = []; List<AdModel> ads = [];
// 选中标签
late LabelModel selectedLabel = LabelModel(); late FilterModel selectedLabel = FilterModel();
// 选中分类
late FilterModel selectedCategory = FilterModel();
// 选中是否收费
late FilterModel selectedFree = FilterModel();
late FilterModel selectedDown = FilterModel();
late TabController tabController = TabController(length:categories.length, vsync: this); late TabController tabController = TabController(length:categories.length, vsync: this);
final EasyRefreshController refreshController = EasyRefreshController(
controlFinishLoad: true,
controlFinishRefresh: true,
);
// 图书列表数据
List<CourseModel> books = [];
List<FilterModel> filterCategories = [];
List<FilterModel> filterLabels = [];
List<FilterModel> filterFree = [
FilterModel(id: '0', name: '收费',selected: false),
FilterModel(id: '1', name: '免费',selected: false)
];
List<FilterModel> filterDown = [
FilterModel(id: 'read_num', name: '读过'),
FilterModel(id: 'rating', name: '评分')
];
final int _limit = 20;
int _page = 1;
bool _noMore = false;
late AnimationController _controller; late AnimationController _controller;
...@@ -54,23 +82,89 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{ ...@@ -54,23 +82,89 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{
// 获取标签数据 // 获取标签数据
_getLabels(); _getLabels();
_getAds(); _getAds();
onRefresh();
super.onReady(); super.onReady();
} }
@override @override
void onClose() { void onClose() {
tabController.dispose(); tabController.dispose();
refreshController.dispose();
super.onClose(); super.onClose();
} }
/// 重置
void resetFilter() {
for(FilterModel model in filterCategories){
model.selected = false;
}
filterCategories.first.selected = true;
for(FilterModel model in filterLabels){
model.selected = false;
}
filterLabels.first.selected = true;
for(FilterModel model in filterFree){
model.selected = false;
}
for(FilterModel model in filterDown){
model.selected = false;
}
update();
}
/// 确定
void sureFilter(){
WidgetsBinding.instance!.addPostFrameCallback((_) {
tabController.animateTo(3); // 你想要的标签索引
});
update();
for(FilterModel model in filterCategories){
if (model.selected){
selectedCategory = model;
}
}
for(FilterModel model in filterLabels){
if(model.selected){
selectedLabel= model;
}
}
for(FilterModel model in filterFree){
if(model.selected){
selectedFree= model;
}
}
void selectLabel(LabelModel model){ for(FilterModel model in filterDown){
for (LabelModel m in labels){ if(model.selected){
selectedDown= model;
}
}
onRefresh();
}
void selectLabel(FilterModel model){
for (FilterModel m in filterLabels){
m.selected = false; m.selected = false;
} }
model.selected = true; model.selected = true;
selectedLabel = model; selectedLabel = model;
update(); onRefresh();
}
void selectCategory(FilterModel model){
for (FilterModel m in filterCategories){
m.selected = false;
}
model.selected = true;
selectedCategory = model;
onRefresh();
} }
/// 获取广告数据 /// 获取广告数据
...@@ -84,15 +178,88 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{ ...@@ -84,15 +178,88 @@ class LibraryController extends GetxController with GetTickerProviderStateMixin{
categories = await LibraryAPI.categories(); categories = await LibraryAPI.categories();
tabController.dispose(); tabController.dispose();
tabController = TabController(length:categories.length, vsync: this); tabController = TabController(length:categories.length, vsync: this);
categories.first.selected = true;
filterCategories = categories.map((model) {
return FilterModel(id: model.categoryId.toString(), name: model.name??'',selected: model.selected);
}).toList();
print('===========$filterCategories');
update(); update();
} }
/// 获取标签数据 /// 获取标签数据
void _getLabels() async { void _getLabels() async {
labels = await LibraryAPI.labels(); labels = await LibraryAPI.labels();
selectedLabel = labels.first;
filterLabels = labels.map((model) {
return FilterModel(id: model.labelId.toString(), name: model.name??'',selected: model.selected);
}).toList();
selectedLabel = filterLabels.first;
selectedLabel.selected = true; selectedLabel.selected = true;
update(['label']); update(['label']);
}
/// 收藏 与 取消收藏
void love({
required String bookId,
required num isCollection
}) async {
if (isCollection == 0){
isCollection = 1;
}
else{
isCollection = 0;
}
bool result = await CommonAPI.love(bookId: bookId, love: isCollection.toString());
if (result) {
onRefresh();
}
}
/// 获取图书列表数据
Future<void> _getBooks([bool isRefresh = false]) async {
if (isRefresh) _page = 1;
// 网路请求
final result = await LibraryAPI.books(
page: _page,
limit: _limit,
categoryId: selectedCategory.id??'',
labelId: selectedLabel.id??'',
isFree: selectedFree.id??'',
sortField: selectedDown.id??''
);
// 如果是刷新 清理数据
if (isRefresh) books.clear();
books.addAll(result);
_page ++;
_noMore = result.length < _limit;
update();
}
void onRefresh() async {
try {
await _getBooks(true);
refreshController.finishRefresh(IndicatorResult.success);
refreshController.resetFooter();
} catch (error) {
refreshController.finishRefresh(IndicatorResult.fail);
}
}
void onLoading() async {
if (_noMore) {
refreshController.finishLoad(IndicatorResult.noMore);
return;
}
try {
await _getBooks();
refreshController.finishLoad();
} catch (error) {
refreshController.finishLoad(IndicatorResult.fail);
}
} }
......
library library; library library;
import 'package:azlistview/azlistview.dart';
import 'package:easy_refresh/easy_refresh.dart'; import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_book/apis/index.dart'; import 'package:flutter_book/apis/index.dart';
...@@ -14,7 +15,6 @@ import '../../models/index.dart'; ...@@ -14,7 +15,6 @@ import '../../models/index.dart';
import '../../routes/index.dart'; import '../../routes/index.dart';
import '../../widgets/index.dart'; import '../../widgets/index.dart';
import '../course/index.dart'; import '../course/index.dart';
import '../library_content/index.dart';
import '../study/index.dart'; import '../study/index.dart';
...@@ -26,4 +26,3 @@ part 'widgets/content.dart'; ...@@ -26,4 +26,3 @@ part 'widgets/content.dart';
part 'widgets/subject.dart'; part 'widgets/subject.dart';
part 'widgets/filter.dart'; part 'widgets/filter.dart';
part 'test.dart'; part 'test.dart';
part 'content_controller.dart';
\ No newline at end of file
...@@ -35,40 +35,65 @@ class _LibraryPageState extends State<LibraryPage> { ...@@ -35,40 +35,65 @@ class _LibraryPageState extends State<LibraryPage> {
return Stack( return Stack(
children: [ children: [
Column( Column(
mainAxisSize: MainAxisSize.max,
children: [ children: [
_buildTab(controller), // _buildTab(controller),
Row(
children: [
Expanded(child: _buildCategory()),
GestureDetector(
onTap: (){
controller.setShow(controller.show);
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10.w),
alignment: Alignment.center,
height: 38.w,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 12.w,
height: 12.w,
// color: Colors.red,
alignment: Alignment.center,
child: Image.asset(
'assets/images/filter.png',
),
),
Gaps.hGaps5,
Text('筛选',style: TextStyle(color: Colours.c9,fontSize: 14.w,height: 1.5),)
],
),
// width: 75,
),
)
],
),
_buildLabel(), _buildLabel(),
GetBuilder<LibraryContentController>( Container(
init: LibraryContentController(), // color: Colors.red,
builder:(contentController)=> Expanded( child: Expanded(
child: CustomPullScrollView( child: CustomPullScrollView(
controller: contentController.refreshController, controller: controller.refreshController,
onRefresh: contentController.onRefresh, // onRefresh: controller.onRefresh,
onLoading: contentController.onLoading, onLoading: controller.onLoading,
child: CustomScrollView( child: SingleChildScrollView(
slivers: [ child: Column(
// 广告位 mainAxisSize: MainAxisSize.max,
SliverToBoxAdapter( children: [
child: Container( controller.ads.isNotEmpty?Container(
color: Colors.red, color: Colors.cyan,
padding: EdgeInsets.symmetric(horizontal: 10.w), child: BuildBanner(items:controller.ads)
child: BuildBanner(items: controller.ads,), ):const SizedBox(),
),
), LibraryContentPage(controller: controller,)
SliverFillRemaining( ],
child: TabBarView( ),
controller: controller.tabController,
children: List.generate(controller.categories.length, (index){
print('=======================================$index');
return LibraryContentPage(controller: contentController,);
})
),
),
],
), ),
), ),
), ),
), )
], ],
), ),
Visibility( Visibility(
...@@ -97,18 +122,46 @@ class _LibraryPageState extends State<LibraryPage> { ...@@ -97,18 +122,46 @@ class _LibraryPageState extends State<LibraryPage> {
scrollDirection:Axis.horizontal , scrollDirection:Axis.horizontal ,
itemBuilder: (BuildContext context, int index){ itemBuilder: (BuildContext context, int index){
return GestureDetector( return GestureDetector(
child: BuildLabelWidget(model: controller.labels[index],), child: BuildLabelWidget(model: controller.filterLabels[index],),
onTap: (){ onTap: (){
controller.selectLabel( controller.labels[index]); controller.selectLabel( controller.filterLabels[index]);
}, },
); );
}, },
itemCount: controller.labels.length, itemCount: controller.filterLabels.length,
), ),
), ),
); );
} }
Widget _buildCategory(){
return Container(
height: 38,
child: GetBuilder<LibraryController>(
init: LibraryController(),
builder: (controller) =>ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index){
FilterModel model = controller.filterCategories[index];
return GestureDetector(
onTap: (){
controller.selectCategory(model);
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 10.w,horizontal: 10.w),
color: model.selected?const Color(0xFFC02D55).withOpacity(0.08):Colors.white,
alignment: Alignment.center,
child: Text(model.name??'',style: model.selected?TextStyle(fontSize: 14.w,color: AppTheme.primary,fontWeight: Fonts.medium,):TextStyle(fontSize: 14.w,color: Colours.c9,),),
),
);
},
itemCount: controller.filterCategories.length
)
),
);
}
PreferredSizeWidget _buildTab(LibraryController controller){ PreferredSizeWidget _buildTab(LibraryController controller){
return PreferredSize( return PreferredSize(
preferredSize: Size.fromHeight(48.w), preferredSize: Size.fromHeight(48.w),
...@@ -128,7 +181,7 @@ class _LibraryPageState extends State<LibraryPage> { ...@@ -128,7 +181,7 @@ class _LibraryPageState extends State<LibraryPage> {
unselectedLabelStyle: TextStyle(color: Colours.c9,fontSize: 14.w,height: 1.5), unselectedLabelStyle: TextStyle(color: Colours.c9,fontSize: 14.w,height: 1.5),
controller: controller.tabController, controller: controller.tabController,
isScrollable: true, isScrollable: true,
tabs: controller.categories.map((model){ tabs: controller.filterCategories.map((model){
return Tab(text: model.name); return Tab(text: model.name);
}).toList(), }).toList(),
), ),
......
part of library; part of library;
class LibraryContentPage extends StatefulWidget { class LibraryContentPage extends StatefulWidget {
final LibraryContentController controller; final LibraryController controller;
// final CategoryModel categoryModel; // final CategoryModel categoryModel;
const LibraryContentPage({ const LibraryContentPage({
Key? key, Key? key,
...@@ -17,7 +17,7 @@ class _LibraryContentPageState extends State<LibraryContentPage> with AutomaticK ...@@ -17,7 +17,7 @@ class _LibraryContentPageState extends State<LibraryContentPage> with AutomaticK
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListView.builder( return ListView.builder(
// shrinkWrap: true, shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
itemCount: widget.controller.books.length, itemCount: widget.controller.books.length,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
......
...@@ -18,13 +18,13 @@ class FilterPage extends StatefulWidget { ...@@ -18,13 +18,13 @@ class FilterPage extends StatefulWidget {
class _FilterPageState extends State<FilterPage> { class _FilterPageState extends State<FilterPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
List<FilterModel> categories = widget.controller.categories.map((model) { // List<FilterModel> categories = widget.controller.categories.map((model) {
return FilterModel(id: model.categoryId.toString(), name: model.name??''); // return FilterModel(id: model.categoryId.toString(), name: model.name??'');
}).toList(); // }).toList();
//
List<FilterModel> labels = widget.controller.labels.map((model) { // List<FilterModel> labels = widget.controller.labels.map((model) {
return FilterModel(id: model.labelId.toString(), name: model.name??''); // return FilterModel(id: model.labelId.toString(), name: model.name??'');
}).toList(); // }).toList();
return Container( return Container(
color: const Color(0xFF000000).withOpacity(0.5), color: const Color(0xFF000000).withOpacity(0.5),
...@@ -39,10 +39,10 @@ class _FilterPageState extends State<FilterPage> { ...@@ -39,10 +39,10 @@ class _FilterPageState extends State<FilterPage> {
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
_buildWrapWidget('分类', categories), _buildWrapWidget('分类', widget.controller.filterCategories),
_buildWrapWidget('标签', labels), _buildWrapWidget('标签', widget.controller.filterLabels),
_buildWrapWidget('是否收费', [FilterModel(id: '0', name: '收费'),FilterModel(id: '1', name: '免费')]), _buildWrapWidget('是否收费', widget.controller.filterFree),
_buildWrapWidget('排序', [FilterModel(id: '0', name: '读过'),FilterModel(id: '1', name: '评分')]), _buildWrapWidget('排序', widget.controller.filterDown),
], ],
) )
], ],
...@@ -58,7 +58,9 @@ class _FilterPageState extends State<FilterPage> { ...@@ -58,7 +58,9 @@ class _FilterPageState extends State<FilterPage> {
children: [ children: [
Expanded( Expanded(
child: GestureDetector( child: GestureDetector(
onTap: widget.resetTap, onTap: (){
widget.controller.resetFilter();
},
child: Container( child: Container(
alignment: Alignment.center, alignment: Alignment.center,
height: 35.w, height: 35.w,
...@@ -105,8 +107,8 @@ class _FilterPageState extends State<FilterPage> { ...@@ -105,8 +107,8 @@ class _FilterPageState extends State<FilterPage> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Container( Container(
margin: EdgeInsets.only(left: 10,bottom: 10,top: 10), margin: EdgeInsets.only(left: 10.w,bottom: 10.w,top: 10.w),
child: Text(title,style: TextStyle(fontSize: 15,height:1.6,color: Colours.c3,fontWeight: Fonts.medium),) child: Text(title,style: TextStyle(fontSize: 15.w,height:1.6,color: Colours.c3,fontWeight: Fonts.medium),)
), ),
Wrap( Wrap(
spacing: 10, spacing: 10,
...@@ -116,9 +118,10 @@ class _FilterPageState extends State<FilterPage> { ...@@ -116,9 +118,10 @@ class _FilterPageState extends State<FilterPage> {
children: data.map((model){ children: data.map((model){
return GestureDetector( return GestureDetector(
onTap: (){ onTap: (){
print('================================');
setState(() { setState(() {
print('--------------------------------${model.selected}'); for (FilterModel model in data){
model.selected = false;
}
model.selected = !model.selected; model.selected = !model.selected;
}); });
}, },
...@@ -126,17 +129,19 @@ class _FilterPageState extends State<FilterPage> { ...@@ -126,17 +129,19 @@ class _FilterPageState extends State<FilterPage> {
height: 27, height: 27,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(13.5), borderRadius: BorderRadius.circular(13.5),
color: model.selected?AppTheme.primary: Colours.cF4 color: model.selected?const Color(0xFFC02D55).withOpacity(0.08): Colours.cF4,
border: model.selected?Border.all(width: 0.5.w,color: AppTheme.primary):null
), ),
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal:15,vertical: 5), padding: const EdgeInsets.symmetric(horizontal:15,vertical: 5),
child: model.name == '读过' || model.name == '评分'?Row( child: model.name == '读过' || model.name == '评分'?Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text(model.name,style: TextStyle(fontSize: 13,height: 1.4,color: model.selected?AppTheme.primary: Colours.c3),textAlign: TextAlign.center,), Text(model.name??'',style: TextStyle(fontSize: 13,height: 1.4,color: model.selected?AppTheme.primary: Colours.c3),textAlign: TextAlign.center,),
Image.asset('assets/images/down.png'), Image.asset(model.selected?'assets/images/filter_select.png':'assets/images/filter_unselect.png'),
], ],
):Text(model.name,style: TextStyle(fontSize: 13,height: 1.4,color: model.selected?AppTheme.primary: Colours.c3),textAlign: TextAlign.center,), ):Text(model.name??'',style: TextStyle(fontSize: 13,height: 1.4,color: model.selected?AppTheme.primary: Colours.c3),textAlign: TextAlign.center,),
), ),
), ),
); );
......
...@@ -2,7 +2,7 @@ part of library; ...@@ -2,7 +2,7 @@ part of library;
class BuildLabelWidget extends StatelessWidget { class BuildLabelWidget extends StatelessWidget {
final LabelModel model; final FilterModel model;
const BuildLabelWidget({ const BuildLabelWidget({
Key? key, Key? key,
required this.model required this.model
......
// part of library_content;
//
// class LibraryContentController extends GetxController {
//
// final CategoryModel categoryModel;
// late LabelModel labelModel;
// LibraryContentController(this.categoryModel, this.labelModel);
//
// final EasyRefreshController refreshController = EasyRefreshController(
// controlFinishLoad: true,
// controlFinishRefresh: true,
// );
//
// // 广告数组
// List<AdModel> ads = [];
//
// final int _limit = 10;
// int _page = 1;
// bool _noMore = false;
//
//
// // 图书列表数据
// List<CourseModel> books = [];
//
//
// @override
// void onReady() {
//
// super.onReady();
// }
//
//
// @override
// void onClose() {
// refreshController.dispose();
// super.onClose();
// }
//
//
// /// 收藏 与 取消收藏
// void love({
// required String bookId,
// required num isCollection
// }) async {
// if (isCollection == 0){
// isCollection = 1;
// }
// else{
// isCollection = 0;
// }
// bool result = await CommonAPI.love(bookId: bookId, love: isCollection.toString());
// if (result) {
// onRefresh();
// }
// }
//
// /// 获取图书列表数据
// Future<void> _getBooks([bool isRefresh = false]) async {
// if (isRefresh) _page = 1;
// // 网路请求
// final result = await LibraryAPI.books(
// page: _page,
// limit: _limit,
// categoryId: categoryModel.categoryId.toString(),
// labelId: labelModel.labelId.toString()
// );
// // 如果是刷新 清理数据
// if (isRefresh) books.clear();
// books.addAll(result);
// _page ++;
// _noMore = result.length < _limit;
// update();
//
// }
//
// void onRefresh() async {
// try {
// await _getBooks(true);
// refreshController.finishRefresh(IndicatorResult.success);
// refreshController.resetFooter();
// } catch (error) {
// refreshController.finishRefresh(IndicatorResult.fail);
// }
// }
//
// void onLoading() async {
// if (_noMore) {
// refreshController.finishLoad(IndicatorResult.noMore);
// return;
// }
// try {
// await _getBooks();
// refreshController.finishLoad();
// } catch (error) {
// refreshController.finishLoad(IndicatorResult.fail);
// }
// }
//
// }
\ No newline at end of file
// library library_content;
//
// import 'package:easy_refresh/easy_refresh.dart';
// import 'package:flutter/material.dart';
// import 'package:get/get.dart';
// import 'package:get/get_state_manager/src/simple/get_controllers.dart';
// import 'package:go_router/go_router.dart';
//
// import '../../apis/index.dart';
// import '../../models/index.dart';
// import '../../routes/index.dart';
// import '../../widgets/index.dart';
// import '../course/index.dart';
// import '../library/index.dart';
//
// part 'view.dart';
// part 'controller.dart';
\ No newline at end of file
// part of library_content;
//
// class LibraryContentPage extends StatefulWidget {
// final CategoryModel categoryModel;
// final LabelModel labelModel;
// final String tag;
// const LibraryContentPage({
// Key? key,
// required this.categoryModel,
// required this.labelModel,
// required this.tag
// }) : super(key: key);
//
// @override
// State<LibraryContentPage> createState() => _LibraryContentPageState();
// }
//
// class _LibraryContentPageState extends State<LibraryContentPage> {
// @override
// Widget build(BuildContext context) {
// return GetBuilder<LibraryContentController>(
// // tag: widget.tag,
// init: LibraryContentController(widget.categoryModel,widget.labelModel),
// builder: (controller) => CustomPullScrollView(
// controller: controller.refreshController,
// onRefresh: controller.onRefresh,
// onLoading: controller.onLoading,
// child: ListView.builder(
// itemCount: controller.books.length+1,
// itemBuilder: (BuildContext context, int index) {
// if (index == 0){
// return Container(
// color: Colors.red,
// padding: const EdgeInsets.symmetric(horizontal: 10),
// child: BuildBanner(items: controller.ads,),
// );
// }
// else {
// CourseModel model = controller.books[index-1];
// return GestureDetector(
// onTap: (){
// context.pushNamed(Routes.bookDetail,queryParameters: {'book_id':model.bookId.toString()});
// },
// child: LibraryCell(model: model,onTap: (){
// controller.love(bookId: model.bookId.toString(), isCollection: model.isCollection!);
// },),
// );
// }
// },
// ),
// ),
// );
// }
// // @override
// // bool get wantKeepAlive => true;
// }
...@@ -60,12 +60,23 @@ class LoginController extends GetxController { ...@@ -60,12 +60,23 @@ class LoginController extends GetxController {
} }
void setCanClick(){ void setCanClick(){
if (ValidatorTool.isValidPhoneNumber(phoneInput.text) && ValidatorTool.isValidPassword(passwordInput.text)){ if (loginType == 0){
_enable = true; if (ValidatorTool.isValidPhoneNumber(phoneInput.text) && ValidatorTool.isValidPassword(passwordInput.text)){
_enable = true;
}
else{
_enable = false;
}
} }
else{ else {
_enable = false; if (ValidatorTool.isValidPhoneNumber(phoneInput.text) && ValidatorTool.isValidCode(codeInput.text)){
_enable = true;
}
else{
_enable = false;
}
} }
update(); update();
} }
...@@ -144,6 +155,10 @@ class LoginController extends GetxController { ...@@ -144,6 +155,10 @@ class LoginController extends GetxController {
} }
void sendCode() async { void sendCode() async {
if (!agree) {
Toast.show('请先阅读并同意《用户协议》和《隐私政策》');
return;
}
final result = await AccountAPI.sendCode(phone: phoneInput.text, type: 'login'); final result = await AccountAPI.sendCode(phone: phoneInput.text, type: 'login');
if (result){ if (result){
Toast.show('发送成功'); Toast.show('发送成功');
......
...@@ -113,6 +113,9 @@ class _LoginPageState extends State<LoginPage> { ...@@ -113,6 +113,9 @@ class _LoginPageState extends State<LoginPage> {
hintText: '请输入验证码', hintText: '请输入验证码',
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
controller: controller.codeInput, controller: controller.codeInput,
onChanged: (text){
controller.setCanClick();
},
), ),
Positioned( Positioned(
right: 10.w, right: 10.w,
......
...@@ -11,6 +11,7 @@ import '../../routes/index.dart'; ...@@ -11,6 +11,7 @@ import '../../routes/index.dart';
import '../../store/index.dart'; import '../../store/index.dart';
import '../book_shop/index.dart'; import '../book_shop/index.dart';
import '../course/index.dart'; import '../course/index.dart';
import '../web/index.dart';
......
...@@ -19,7 +19,7 @@ class MineController extends GetxController { ...@@ -19,7 +19,7 @@ class MineController extends GetxController {
@override @override
void onReady() { void onReady() {
_getAds(); _getAds();
_getNums(); getNums();
getInfo(); getInfo();
super.onReady(); super.onReady();
} }
...@@ -31,7 +31,7 @@ class MineController extends GetxController { ...@@ -31,7 +31,7 @@ class MineController extends GetxController {
} }
/// 消息未读数 /// 消息未读数
void _getNums() async { void getNums() async {
num = await CommonAPI.num(); num = await CommonAPI.num();
update(); update();
} }
......
...@@ -42,9 +42,13 @@ class _MinePageState extends State<MinePage> { ...@@ -42,9 +42,13 @@ class _MinePageState extends State<MinePage> {
onPressed: () => context.pushNamed(Routes.set), onPressed: () => context.pushNamed(Routes.set),
), ),
GestureDetector( GestureDetector(
onTap: (){ onTap: () async{
context.pushNamed(Routes.msgs); final result = await context.pushNamed(Routes.msgs);
// controller.logout(context);
print('---------------------------------1111$result');
if (result == true){
controller.getNums();
}
}, },
child: badges.Badge( child: badges.Badge(
position: badges.BadgePosition.topEnd(top: -5, end: 0), position: badges.BadgePosition.topEnd(top: -5, end: 0),
......
part of pay_coupon; part of pay_coupon;
class PayCouponController extends GetxController { class PayCouponController extends GetxController with GetSingleTickerProviderStateMixin{
late TabController tabController; final String tag;
List <Widget>tabs = [ final BookPayController payController;
const Tab(text: '可用',), PayCouponController(this.tag,this.payController){
const Tab(text: '不可用',), // tabs = [
]; // Tab(text: '可用(${payController.couponNumModel.availableNum})',),
// Tab(text: '不可用(${payController.couponNumModel.unavailableNum})',),
// ];
}
// List <Widget>tabs = [];
// late TabController tabController = TabController(length:tabs.length, vsync: this);
final EasyRefreshController refreshController = EasyRefreshController(
controlFinishLoad: true,
controlFinishRefresh: true,
);
CouponListModel couponListModel = CouponListModel();
// 优惠券
List <CouponModel> coupons = [];
final int _limit = 10;
int _page = 1;
bool _noMore = false;
Future<void> _getCoupon([bool isRefresh = false]) async {
if (isRefresh) _page = 1;
// 网路请求
final result = await ShopAPI.coupon(
page: _page,
limit: _limit,
type: tag,
price: payController.finalPrice.toString()
);
for(CouponModel model in result.list!) {
print('================================${tag}');
model.type = num.parse(tag);
}
// 如果是刷新 清理数据
if (isRefresh) coupons.clear();
coupons.addAll(result.list!);
_page ++;
_noMore = result.list!.length < _limit;
update();
}
void onRefresh() async {
try {
await _getCoupon(true);
refreshController.finishRefresh(IndicatorResult.success);
refreshController.resetFooter();
} catch (error) {
print('--------------------------------$error');
refreshController.finishRefresh(IndicatorResult.fail);
}
}
void onLoading() async {
if (_noMore) {
refreshController.finishLoad(IndicatorResult.noMore);
return;
}
try {
await _getCoupon();
refreshController.finishLoad();
} catch (error) {
refreshController.finishLoad(IndicatorResult.fail);
}
}
} }
\ No newline at end of file
library pay_coupon; library pay_coupon;
import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_book/pages/user_coupon/index.dart'; import 'package:flutter_book/pages/user_coupon/index.dart';
import 'package:flutter_book/widgets/index.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:go_router/go_router.dart';
import '../../apis/index.dart';
import '../../models/index.dart';
import '../../theme.dart'; import '../../theme.dart';
import '../../utils/index.dart'; import '../../utils/index.dart';
import '../book_pay/index.dart';
part 'view.dart'; part 'view.dart';
part 'controller.dart'; part 'controller.dart';
\ No newline at end of file part 'widgets/item.dart';
...@@ -3,18 +3,34 @@ part of pay_coupon; ...@@ -3,18 +3,34 @@ part of pay_coupon;
class PayCouponPage extends StatefulWidget { class PayCouponPage extends StatefulWidget {
const PayCouponPage({Key? key}) : super(key: key); final BookPayController payController;
const PayCouponPage({
Key? key,
required this.payController
}) : super(key: key);
@override @override
State<PayCouponPage> createState() => _PayCouponPageState(); State<PayCouponPage> createState() => _PayCouponPageState();
} }
class _PayCouponPageState extends State<PayCouponPage> { class _PayCouponPageState extends State<PayCouponPage> with SingleTickerProviderStateMixin{
List <Widget> tabs= [];
late TabController tabController;
@override
void initState() {
tabs = [
Tab(text: '可用(${widget.payController.couponNumModel.availableNum})',),
Tab(text: '不可用(${widget.payController.couponNumModel.unavailableNum})',),
];
tabController = TabController(length:tabs.length, vsync: this);
super.initState();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GetBuilder<PayCouponController>( return Scaffold(
init: PayCouponController(),
builder: (controller) =>Scaffold(
appBar: AppBar( appBar: AppBar(
centerTitle: true, centerTitle: true,
title: const Text('选择优惠券'), title: const Text('选择优惠券'),
...@@ -22,49 +38,73 @@ class _PayCouponPageState extends State<PayCouponPage> { ...@@ -22,49 +38,73 @@ class _PayCouponPageState extends State<PayCouponPage> {
body: Column( body: Column(
children: [ children: [
TabBar( TabBar(
labelColor: AppTheme.primary, labelColor: Colours.c3,
// isScrollable: true,
labelStyle: TextStyle(fontSize: 15.w,height: 1.4,fontWeight: Fonts.medium), labelStyle: TextStyle(fontSize: 15.w,height: 1.4,fontWeight: Fonts.medium),
unselectedLabelColor: Colours.c9, unselectedLabelColor: Colours.c9,
unselectedLabelStyle: TextStyle(fontSize: 15.w,height: 1.4), unselectedLabelStyle: TextStyle(fontSize: 15.w,height: 1.4),
indicatorSize: TabBarIndicatorSize.label, indicatorSize: TabBarIndicatorSize.label,
indicatorColor: AppTheme.primary, indicatorColor: AppTheme.primary,
tabs:controller.tabs, tabs:tabs,
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
controller: controller.tabController, controller: tabController,
), ),
Expanded( Expanded(
child: TabBarView( child: TabBarView(
controller: controller.tabController, controller: tabController,
children: [ children: List.generate(tabs.length, (index){
return CouponPage(tag:'${1-index}',payController: widget.payController,);
], })
), ),
), ),
], ],
), ),
), );
);
} }
} }
class CouponPage extends StatefulWidget { class CouponPage extends StatefulWidget {
const CouponPage({Key? key}) : super(key: key); final String tag;
final BookPayController payController;
const CouponPage({
Key? key,
required this.tag,
required this.payController
}) : super(key: key);
@override @override
State<CouponPage> createState() => _CouponPageState(); State<CouponPage> createState() => _CouponPageState();
} }
class _CouponPageState extends State<CouponPage> { class _CouponPageState extends State<CouponPage> with AutomaticKeepAliveClientMixin{
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListView.builder( return GetBuilder<PayCouponController>(
itemBuilder: (BuildContext context, int index){ tag: widget.tag,
// return BuildItem(model: ,); init: PayCouponController(widget.tag,widget.payController),
}, builder: (controller) =>CustomPullScrollView(
itemCount: 2, controller: controller.refreshController,
onRefresh: controller.onRefresh,
onLoading: controller.onLoading,
child: ListView.builder(
itemBuilder: (BuildContext context, int index){
CouponModel model = controller.coupons[index];
return BuildItem(model:model,useTap: (){
widget.payController.setUseCoupon(model);
context.pop();
},);
},
itemCount: controller.coupons.length,
),
),
); );
} }
@override
bool get wantKeepAlive => true;
} }
part of pay_coupon;
class BuildItem extends StatelessWidget {
final CouponModel model;
final void Function()? useTap;
const BuildItem({
Key? key,
required this.model,
required this.useTap
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(left: 10.w,top: 10.w,right: 10.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.w),
color: Colors.white,
boxShadow: [
BoxShadow(
color: const Color(0xFFC7C7C7).withOpacity(0.5),
offset: Offset(3.w, 0),
blurRadius: 10.w,
spreadRadius: 0.w,
),
],
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Stack(
children: [
Image.asset(model.type ==1?'assets/images/coupon_yes.png':'assets/images/coupon_no.png'),
Positioned(
left: 0.w,
right: 0.w,
bottom: 0.w,
top: 0.w,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
RichText(
text: TextSpan(
children: <TextSpan>[
TextSpan(
text: '¥',
style: TextStyle(fontSize: 15.w,fontWeight: Fonts.boldSemi,height: 1.5,color: model.type ==1?Colors.white:Colours.cC8)
),
TextSpan(
text: model.reducedPrice??'',
style: TextStyle(fontSize: 40.w,fontWeight: Fonts.boldSemi,height: 1.5,color: model.type ==1?Colors.white:Colours.cC8)
),
]
),
),
Text('满${model.normPrice}可用',style: TextStyle(fontSize: 11.w,height: 1.5,color: model.type ==1?Colors.white:Colours.cC8),)
],
),
)
],
),
Expanded(
child: Container(
margin: EdgeInsets.only(left:15.w,right: 15.w ),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(model.couponName??'',style: TextStyle(fontSize: 16.w,fontWeight: Fonts.medium,height: 1.5,color: model.type ==1?Colours.c3:Colours.c9),),
Gaps.vGaps5,
Text('满${model.normPrice}${model.reducedPrice}元',style: TextStyle(fontSize: 12.w,height: 1.5,color: Colours.c9),),
Gaps.vGaps5,
Text('有效至:${model.endTime}',style: TextStyle(fontSize: 12.w,height: 1.5,color: Colours.c9),),
],
),
if (model.type == 1) GestureDetector(
onTap: useTap,
child: Container(
width: 65.w,
height: 24.w,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.w),
color: Colors.white,
border: Border.all(width: 1.w,color: AppTheme.primary)
),
child: Text('立即使用',style: TextStyle(fontSize: 12.w,fontWeight: Fonts.medium,color: AppTheme.primary),),
),
) else const SizedBox()
],
),
),
)
],
)
);
}
}
...@@ -52,7 +52,9 @@ class ResetPwdController extends GetxController { ...@@ -52,7 +52,9 @@ class ResetPwdController extends GetxController {
); );
if (result){ if (result){
if (context.mounted){ if (context.mounted){
context.goNamed(Routes.login); // context.goNamed(Routes.login);
context.pop();
context.pop();
} }
} }
else{ else{
......
...@@ -76,7 +76,6 @@ class _ResetPwdPageState extends State<ResetPwdPage> { ...@@ -76,7 +76,6 @@ class _ResetPwdPageState extends State<ResetPwdPage> {
isEnabled: controller.enable, isEnabled: controller.enable,
onPressed: () { onPressed: () {
controller.resetPassword(context); controller.resetPassword(context);
// context.goNamed(Routes.login);
}, },
) )
], ],
......
...@@ -2,6 +2,7 @@ library splash_page; ...@@ -2,6 +2,7 @@ library splash_page;
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_book/apis/index.dart';
import 'package:flutter_book/widgets/index.dart'; import 'package:flutter_book/widgets/index.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
......
...@@ -15,11 +15,13 @@ class _SplashPageState extends State<SplashPage> { ...@@ -15,11 +15,13 @@ class _SplashPageState extends State<SplashPage> {
Future.wait([ Future.wait([
Future.delayed(const Duration(seconds: 2)) Future.delayed(const Duration(seconds: 2))
]).whenComplete(() async { ]).whenComplete(() async {
// final userModel = await AccountAPI.login(phone: '18337678567', password: '013790d7eb52197bead4c757ebfae7cf', type: '1'); final ads = await CommonAPI.list(type: '1');
// Console.log('++++++++++++++++'); if (ads.isNotEmpty){
// Console.log(userModel.name); context.pushReplacementNamed(Routes.ad,extra: ads);
// context.goNamed(Routes.main); }
context.pushReplacementNamed(Routes.ad); else {
context.pushReplacementNamed(Routes.main);
}
}); });
...@@ -47,10 +49,10 @@ class _SplashPageState extends State<SplashPage> { ...@@ -47,10 +49,10 @@ class _SplashPageState extends State<SplashPage> {
), ),
) )
), ),
Expanded( // Expanded(
flex: 2, // flex: 2,
child: Center(child: CupertinoActivityIndicator(),), // child: Center(child: CupertinoActivityIndicator(),),
) // )
], ],
), ),
); );
......
part of study_report;
class StudyReportController extends GetxController {
final String bookId;
StudyReportController(this.bookId);
ReportModel model = ReportModel();
@override
void onReady() {
_getReport();
super.onReady();
}
void _getReport() async {
model = await LibraryAPI.report(bookId: bookId);
update();
}
}
\ No newline at end of file
library study_report; library study_report;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_book/apis/index.dart';
import 'package:flutter_book/utils/index.dart'; import 'package:flutter_book/utils/index.dart';
import 'package:flutter_book/widgets/index.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get_state_manager/src/simple/get_controllers.dart';
import 'package:get/get_state_manager/src/simple/get_state.dart';
import '../../models/index.dart';
part 'view.dart'; part 'view.dart';
part 'widgets/card.dart'; part 'widgets/card.dart';
\ No newline at end of file part 'controller.dart';
\ No newline at end of file
part of study_report; part of study_report;
class BuildCard extends StatelessWidget { class BuildCard extends StatelessWidget {
const BuildCard({Key? key}) : super(key: key); final ReportModel model;
const BuildCard({
Key? key,
required this.model
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
...@@ -10,6 +14,8 @@ class BuildCard extends StatelessWidget { ...@@ -10,6 +14,8 @@ class BuildCard extends StatelessWidget {
Container( Container(
child: Image.asset( child: Image.asset(
'assets/images/report_bg.png', 'assets/images/report_bg.png',
width: double.infinity,
fit: BoxFit.contain,
), ),
), ),
Positioned( Positioned(
...@@ -27,13 +33,13 @@ class BuildCard extends StatelessWidget { ...@@ -27,13 +33,13 @@ class BuildCard extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text('恰如其分的孤独',style: TextStyle(fontSize: 20.w,height: 1.4,color: Colors.white,fontWeight: Fonts.medium),), Text(model.bookName??'',style: TextStyle(fontSize: 20.w,height: 1.4,color: Colors.white,fontWeight: Fonts.medium),),
Gaps.vGaps15, Gaps.vGaps15,
Row( Row(
children: [ children: [
Text('学习总进度',style: TextStyle(fontSize: 13.w,height: 1.4,color: Colors.white),), Text('学习总进度',style: TextStyle(fontSize: 13.w,height: 1.4,color: Colors.white),),
Gaps.hGaps15, Gaps.hGaps15,
Text('4.98%',style: TextStyle(fontSize: 16.w,height: 1.4,color: Colors.white,fontWeight: Fonts.medium),), Text(model.progress??'',style: TextStyle(fontSize: 16.w,height: 1.4,color: Colors.white,fontWeight: Fonts.medium),),
] ]
), ),
Gaps.vGaps10, Gaps.vGaps10,
...@@ -41,20 +47,20 @@ class BuildCard extends StatelessWidget { ...@@ -41,20 +47,20 @@ class BuildCard extends StatelessWidget {
children: [ children: [
Text('学习总时长',style: TextStyle(fontSize: 13.w,height: 1.4,color: Colors.white),), Text('学习总时长',style: TextStyle(fontSize: 13.w,height: 1.4,color: Colors.white),),
Gaps.hGaps15, Gaps.hGaps15,
Text('30分钟',style: TextStyle(fontSize: 16.w,height: 1.4,color: Colors.white,fontWeight: Fonts.medium),), Text('${model.readSecond??''}分钟',style: TextStyle(fontSize: 16.w,height: 1.4,color: Colors.white,fontWeight: Fonts.medium),),
] ]
), ),
Gaps.vGaps10, Gaps.vGaps10,
Text('上次读到',style: TextStyle(fontSize: 13.w,height: 1.4,color: Colors.white),), Text('上次读到',style: TextStyle(fontSize: 13.w,height: 1.4,color: Colors.white),),
Gaps.vGaps5, Gaps.vGaps5,
Text('第3章 情节…情节…情节情节情节情节',style: TextStyle(fontSize: 16.w,height: 1.4,color: Colors.white,fontWeight: Fonts.medium),maxLines: 1,overflow: TextOverflow.ellipsis,), Text(model.lastChapter??'',style: TextStyle(fontSize: 16.w,height: 1.4,color: Colors.white,fontWeight: Fonts.medium),maxLines: 1,overflow: TextOverflow.ellipsis,),
] ]
), ),
), ),
Container( Container(
height: 120.w, height: 120.w,
width: 100.w, width: 100.w,
color: Colors.lime, child: CustomImage.asset(url: model.img??''),
) )
], ],
), ),
......
...@@ -7,12 +7,22 @@ class CoinRechargeController extends GetxController { ...@@ -7,12 +7,22 @@ class CoinRechargeController extends GetxController {
PayModel(type: 1, name: '微信', icon: 'assets/images/pay_wechat.png', selected: true), PayModel(type: 1, name: '微信', icon: 'assets/images/pay_wechat.png', selected: true),
PayModel(type: 2, name: '支付宝', icon: 'assets/images/pay_ali.png', selected: false), PayModel(type: 2, name: '支付宝', icon: 'assets/images/pay_ali.png', selected: false),
]; ];
List<CoinModel> data = [];
late CoinModel rechargeModel = CoinModel();
// 支付方式 // 支付方式
late PayModel _payModel = pays.first; late PayModel _payModel = pays.first;
PayModel get payModel => _payModel; PayModel get payModel => _payModel;
@override
void onReady() {
_getlist();
super.onReady();
}
void setPayModel(PayModel payModel){ void setPayModel(PayModel payModel){
for (PayModel model in pays) { for (PayModel model in pays) {
if (model.type == payModel.type){ if (model.type == payModel.type){
...@@ -25,4 +35,29 @@ class CoinRechargeController extends GetxController { ...@@ -25,4 +35,29 @@ class CoinRechargeController extends GetxController {
} }
update(); update();
} }
void choose(CoinModel coinModel){
for (CoinModel model in data) {
model.selected = (model == coinModel);
}
rechargeModel = coinModel;
update();
}
void _getlist()async{
String type = '';
if(Platform.isIOS){
type = 'ios';
}
if(Platform.isAndroid){
type = 'android';
}
final result = await MineAPI.coinsRechargeList(type: type);
data = result;
update();
}
} }
\ No newline at end of file
...@@ -2,11 +2,14 @@ library recharge; ...@@ -2,11 +2,14 @@ library recharge;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_book/apis/index.dart';
import 'package:flutter_book/models/index.dart';
import 'package:flutter_book/theme.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:get/get_state_manager/src/simple/get_controllers.dart'; import 'package:get/get_state_manager/src/simple/get_controllers.dart';
import 'package:go_router/go_router.dart';
import '../../models/shop.dart';
import '../../utils/index.dart'; import '../../utils/index.dart';
import '../../widgets/index.dart'; import '../../widgets/index.dart';
import '../book_pay/index.dart'; import '../book_pay/index.dart';
......
...@@ -14,74 +14,76 @@ class _CoinRechargePageState extends State<CoinRechargePage> { ...@@ -14,74 +14,76 @@ class _CoinRechargePageState extends State<CoinRechargePage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GetBuilder<CoinRechargeController>( return GetBuilder<CoinRechargeController>(
init: CoinRechargeController(), init: CoinRechargeController(),
builder:(controller) => Container( builder:(controller) => Column(
// height: 100, mainAxisSize: MainAxisSize.min,
// color: Colors.amberAccent, children: [
child: Column( Container(
mainAxisSize: MainAxisSize.min, color: Colors.white,
children: [ padding: EdgeInsets.symmetric(vertical: 17.w),
Container( width: double.infinity,
padding: EdgeInsets.symmetric(vertical: 17), margin: EdgeInsets.fromLTRB(10.w, 0.w, 10.w, 0.w),
width: double.infinity, child: Container(
margin: EdgeInsets.fromLTRB(10, 10, 10, 0), // color: Colors.red,
child: Container( child:Stack(
color: Colors.red, children: [
child:Stack( const Row(
children: [ mainAxisAlignment: MainAxisAlignment.center,
Row( children: [
mainAxisAlignment: MainAxisAlignment.center, Text('紫荆币充值',textAlign:TextAlign.center),
children: [ ],
Text('紫荆币充值',textAlign:TextAlign.center), ),
], Positioned(
), right: 0.w,
Positioned( top: 0.w,
right: 0, child: GestureDetector(
top: 0, onTap: (){
child: Container( context.pop();
width: 20, },
height: 20, child: SizedBox(
color: Colors.green, width: 20.w,
height: 20.w,
child: Image.asset('assets/images/close.png'),
), ),
) ),
], )
) ],
), )
),
Container(
margin: EdgeInsets.symmetric(horizontal: 20),
child: _buildAudioGridView()
), ),
Gaps.vGaps15, ),
_buildListView(controller), Container(
Gaps.vGaps15, margin: EdgeInsets.symmetric(horizontal: 20.w),
Container( child: _buildAudioGridView(controller)
margin: EdgeInsets.symmetric(horizontal:15), ),
child: CustomGradientButton( Gaps.vGaps15,
text: '立即充值', _buildListView(controller),
isEnabled: true, Gaps.vGaps15,
onPressed: () { Container(
// context.goNamed(Routes.login); margin: EdgeInsets.symmetric(horizontal:15.w),
}, child: CustomGradientButton(
), text: '立即充值${controller.rechargeModel.priceName??''}',
isEnabled: true,
onPressed: () {
// context.goNamed(Routes.login);
},
), ),
Gaps.vGaps15, ),
RichText(text: TextSpan( Gaps.vGaps15,
children: [ RichText(text: TextSpan(
TextSpan(text: '充值即代表同意',style: TextStyle(fontSize: 13.w,height: 1.5,color: Colours.c9)), children: [
TextSpan(text: '《用户充值协议》',style: TextStyle(fontSize: 13.w,height: 1.5,color: Color(0xFF2A82D9))), TextSpan(text: '充值即代表同意',style: TextStyle(fontSize: 13.w,height: 1.5,color: Colours.c9)),
] TextSpan(text: '《用户充值协议》',style: TextStyle(fontSize: 13.w,height: 1.5,color: Color(0xFF2A82D9))),
)), ]
Gaps.vGaps15 )),
], Gaps.vGaps15
), ],
), ),
); );
} }
Widget _buildAudioGridView(){ Widget _buildAudioGridView(CoinRechargeController controller){
return GridView.builder( return GridView.builder(
// padding: const EdgeInsets.only(left: 13,top: 10), // padding: const EdgeInsets.only(left: 13,top: 10),
physics: NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, crossAxisCount: 3,
...@@ -90,23 +92,29 @@ class _CoinRechargePageState extends State<CoinRechargePage> { ...@@ -90,23 +92,29 @@ class _CoinRechargePageState extends State<CoinRechargePage> {
childAspectRatio: 2 childAspectRatio: 2
), ),
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
return Container( CoinModel model = controller.data[index];
decoration: BoxDecoration( return GestureDetector(
color: Colors.red, onTap: (){
borderRadius: BorderRadius.circular(8.w), controller.choose(model);
border: Border.all(width: 0.5.w,color: Color(0xFFDADADA)) },
), child: Container(
decoration: BoxDecoration(
color: model.selected?AppTheme.primary.withOpacity(0.1):Colors.white,
borderRadius: BorderRadius.circular(8.w),
border: Border.all(width: 0.5.w,color: model.selected?AppTheme.primary:const Color(0xFFDADADA))
),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text('42紫荆币',style: TextStyle(color: Colours.c3,fontSize: 14,height: 1.5),), Text(model.beanName??'',style: TextStyle(color: model.selected?AppTheme.primary:Colours.c3,fontSize: 14.w,height: 1.5),),
Text('6元',style: TextStyle(color: Colours.c9,fontSize: 11,height: 1.5),), Text(model.priceName??'',style: TextStyle(color: model.selected?AppTheme.primary:Colours.c9,fontSize: 11.w,height: 1.5),),
], ],
),
), ),
); );
}, },
itemCount: 6, itemCount: controller.data.length,
); );
} }
Widget _buildListView(CoinRechargeController controller){ Widget _buildListView(CoinRechargeController controller){
......
...@@ -31,7 +31,7 @@ class UserCouponController extends GetxController { ...@@ -31,7 +31,7 @@ class UserCouponController extends GetxController {
_getCoupon(); _getCoupon();
} }
/// 获取课程内图书列表 /// 获取我的优惠券
Future<void> _getCoupon([bool isRefresh = false]) async { Future<void> _getCoupon([bool isRefresh = false]) async {
if (isRefresh) _page = 1; if (isRefresh) _page = 1;
// 网路请求 // 网路请求
......
...@@ -8,6 +8,7 @@ import 'package:flutter_book/utils/index.dart'; ...@@ -8,6 +8,7 @@ import 'package:flutter_book/utils/index.dart';
import 'package:flutter_book/widgets/index.dart'; import 'package:flutter_book/widgets/index.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:go_router/go_router.dart';
import '../../models/index.dart'; import '../../models/index.dart';
......
...@@ -11,36 +11,42 @@ class UserCouponPage extends StatefulWidget { ...@@ -11,36 +11,42 @@ class UserCouponPage extends StatefulWidget {
class _UserCouponPageState extends State<UserCouponPage> { class _UserCouponPageState extends State<UserCouponPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GetBuilder<UserCouponController>( return WillPopScope(
init: UserCouponController(), onWillPop: () async {
builder:(controller) => Scaffold( context.pop(true);
appBar: AppBar( return false;
centerTitle: true, },
title: const Text('优惠券'), child: GetBuilder<UserCouponController>(
), init: UserCouponController(),
body: CustomPullScrollView( builder:(controller) => Scaffold(
controller: controller.refreshController, appBar: AppBar(
onRefresh: controller.onRefresh, centerTitle: true,
onLoading: controller.onLoading, title: const Text('优惠券'),
child: ListView.builder( ),
itemBuilder: (BuildContext context, int index){ body: CustomPullScrollView(
if (index == controller.coupons.length){ controller: controller.refreshController,
return GestureDetector( onRefresh: controller.onRefresh,
onTap: (){ onLoading: controller.onLoading,
controller.getOverCoupons(); child: ListView.builder(
}, itemBuilder: (BuildContext context, int index){
child: Container( if (index == controller.coupons.length){
height: 40.w, return GestureDetector(
color: Colors.cyan, onTap: (){
child: Text('过期优惠券'), controller.getOverCoupons();
), },
); child: Container(
} height: 40.w,
else { color: Colors.cyan,
return BuildItem(model: controller.coupons[index],); child: Text('过期优惠券'),
} ),
}, );
itemCount: controller.coupons.length +1, }
else {
return BuildItem(model: controller.coupons[index],);
}
},
itemCount: controller.coupons.length +1,
),
), ),
), ),
), ),
......
...@@ -65,7 +65,7 @@ class BuildItem extends StatelessWidget { ...@@ -65,7 +65,7 @@ class BuildItem extends StatelessWidget {
Gaps.vGaps5, Gaps.vGaps5,
Text('满${model.normPrice}${model.reducedPrice}元',style: TextStyle(fontSize: 12.w,height: 1.5,color: Colours.c9),), Text('满${model.normPrice}${model.reducedPrice}元',style: TextStyle(fontSize: 12.w,height: 1.5,color: Colours.c9),),
Gaps.vGaps5, Gaps.vGaps5,
Text(model.endTime??'',style: TextStyle(fontSize: 12.w,height: 1.5,color: Colours.c9),), // Text(model.endTime??'',style: TextStyle(fontSize: 12.w,height: 1.5,color: Colours.c9),),
], ],
), ),
Container( Container(
......
...@@ -17,30 +17,19 @@ class _UserDiscussPageState extends State<UserDiscussPage> { ...@@ -17,30 +17,19 @@ class _UserDiscussPageState extends State<UserDiscussPage> {
centerTitle: true, centerTitle: true,
title: const Text('讨论'), title: const Text('讨论'),
), ),
body: Container( body: Column(
color: Colors.transparent, crossAxisAlignment: CrossAxisAlignment.start,
child: CustomPullScrollView( children: [
controller: controller.refreshController, Container(
// onRefresh: controller.onRefresh, margin: EdgeInsets.only(left: 22.5.w,top: 16.w),
onLoading: controller.onLoading, child: Text('共${controller.discuss.length}本书',style: TextStyle(fontSize: 13.w,height: 1.5,color: Colours.c6,fontWeight: Fonts.medium),)
child:SingleChildScrollView( ),
child: Container( Expanded(
margin: EdgeInsets.all(10.w), child: CustomPullScrollView(
decoration: BoxDecoration( controller: controller.refreshController,
borderRadius: BorderRadius.circular(8.w), onRefresh: controller.onRefresh,
color: Colors.white, onLoading: controller.onLoading,
boxShadow: [ child:ListView.builder(
BoxShadow(
color: const Color(0xFFC7C7C7).withOpacity(0.5),
offset: Offset(3.w, 0),
blurRadius: 10.w,
spreadRadius: 0.w,
),
],
),
child: ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index){ itemBuilder: (BuildContext context, int index){
return GestureDetector( return GestureDetector(
onTap: (){ onTap: (){
...@@ -50,10 +39,10 @@ class _UserDiscussPageState extends State<UserDiscussPage> { ...@@ -50,10 +39,10 @@ class _UserDiscussPageState extends State<UserDiscussPage> {
); );
}, },
itemCount: controller.discuss.length, itemCount: controller.discuss.length,
), )
), ),
) ),
), ],
), ),
), ),
); );
......
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论