提交 d9047aec authored 作者: maodou's avatar maodou

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

# Conflicts: # lib/pages/book_pay/controller.dart # pubspec.yaml
...@@ -4,6 +4,8 @@ PODS: ...@@ -4,6 +4,8 @@ PODS:
- Flutter (1.0.0) - Flutter (1.0.0)
- flutter_app_update (0.0.1): - flutter_app_update (0.0.1):
- Flutter - Flutter
- flutter_inapp_purchase (0.0.1):
- Flutter
- flutter_inappwebview (0.0.1): - flutter_inappwebview (0.0.1):
- Flutter - Flutter
- flutter_inappwebview/Core (= 0.0.1) - flutter_inappwebview/Core (= 0.0.1)
...@@ -36,12 +38,18 @@ PODS: ...@@ -36,12 +38,18 @@ PODS:
- shared_preferences_foundation (0.0.1): - shared_preferences_foundation (0.0.1):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
- tobias (0.0.1):
- Flutter
- tobias/normal (= 0.0.1)
- tobias/normal (0.0.1):
- Flutter
- WechatOpenSDK-XCFramework (2.0.2) - WechatOpenSDK-XCFramework (2.0.2)
DEPENDENCIES: DEPENDENCIES:
- audio_session (from `.symlinks/plugins/audio_session/ios`) - audio_session (from `.symlinks/plugins/audio_session/ios`)
- Flutter (from `Flutter`) - Flutter (from `Flutter`)
- flutter_app_update (from `.symlinks/plugins/flutter_app_update/ios`) - flutter_app_update (from `.symlinks/plugins/flutter_app_update/ios`)
- flutter_inapp_purchase (from `.symlinks/plugins/flutter_inapp_purchase/ios`)
- flutter_inappwebview (from `.symlinks/plugins/flutter_inappwebview/ios`) - flutter_inappwebview (from `.symlinks/plugins/flutter_inappwebview/ios`)
- flutter_sound (from `.symlinks/plugins/flutter_sound/ios`) - flutter_sound (from `.symlinks/plugins/flutter_sound/ios`)
- flutter_tts (from `.symlinks/plugins/flutter_tts/ios`) - flutter_tts (from `.symlinks/plugins/flutter_tts/ios`)
...@@ -51,6 +59,7 @@ DEPENDENCIES: ...@@ -51,6 +59,7 @@ DEPENDENCIES:
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- tobias (from `.symlinks/plugins/tobias/ios`)
SPEC REPOS: SPEC REPOS:
trunk: trunk:
...@@ -65,6 +74,8 @@ EXTERNAL SOURCES: ...@@ -65,6 +74,8 @@ EXTERNAL SOURCES:
:path: Flutter :path: Flutter
flutter_app_update: flutter_app_update:
:path: ".symlinks/plugins/flutter_app_update/ios" :path: ".symlinks/plugins/flutter_app_update/ios"
flutter_inapp_purchase:
:path: ".symlinks/plugins/flutter_inapp_purchase/ios"
flutter_inappwebview: flutter_inappwebview:
:path: ".symlinks/plugins/flutter_inappwebview/ios" :path: ".symlinks/plugins/flutter_inappwebview/ios"
flutter_sound: flutter_sound:
...@@ -83,11 +94,14 @@ EXTERNAL SOURCES: ...@@ -83,11 +94,14 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/permission_handler_apple/ios" :path: ".symlinks/plugins/permission_handler_apple/ios"
shared_preferences_foundation: shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin" :path: ".symlinks/plugins/shared_preferences_foundation/darwin"
tobias:
:path: ".symlinks/plugins/tobias/ios"
SPEC CHECKSUMS: SPEC CHECKSUMS:
audio_session: 4f3e461722055d21515cf3261b64c973c062f345 audio_session: 4f3e461722055d21515cf3261b64c973c062f345
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_app_update: 65f61da626cb111d1b24674abc4b01728d7723bc flutter_app_update: 65f61da626cb111d1b24674abc4b01728d7723bc
flutter_inapp_purchase: 5c6a1ac3f11b11d0c8c0321c0c41c1f05805e4c8
flutter_inappwebview: 3d32228f1304635e7c028b0d4252937730bbc6cf flutter_inappwebview: 3d32228f1304635e7c028b0d4252937730bbc6cf
flutter_sound: c60effa2a350fb977885f0db2fbc4c1ad5160900 flutter_sound: c60effa2a350fb977885f0db2fbc4c1ad5160900
flutter_sound_core: 26c10e5832e76aaacfae252d8925232281c486ae flutter_sound_core: 26c10e5832e76aaacfae252d8925232281c486ae
...@@ -99,6 +113,7 @@ SPEC CHECKSUMS: ...@@ -99,6 +113,7 @@ SPEC CHECKSUMS:
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
tobias: 22f69183b14af82a2ac8ff698af084c352744e5f
WechatOpenSDK-XCFramework: acdeeda129efbef9532bca8a10c24e1b4b8c7d69 WechatOpenSDK-XCFramework: acdeeda129efbef9532bca8a10c24e1b4b8c7d69
PODFILE CHECKSUM: d88b567994d32cfdf2f8417e66666d472921c85e PODFILE CHECKSUM: d88b567994d32cfdf2f8417e66666d472921c85e
......
...@@ -153,11 +153,13 @@ abstract class CommonAPI { ...@@ -153,11 +153,13 @@ abstract class CommonAPI {
/// 10、上传文件 /// 10、上传文件
static Future <String> upload({ static Future <String> upload({
required String path required String path,
required String fileTypes
}) async { }) async {
final result = await HttpService.to.upload( final result = await HttpService.to.upload(
'/v1/members/Information/uploadFile', '/v1/members/Information/uploadFile',
path: path path: path,
fileTypes: fileTypes
); );
if (result.data is! Map) return ''; if (result.data is! Map) return '';
return result.data['filesUrl']; return result.data['filesUrl'];
......
...@@ -366,5 +366,23 @@ abstract class MineAPI { ...@@ -366,5 +366,23 @@ abstract class MineAPI {
} }
return false; return false;
} }
/// 20、紫荆币充值创建订单
static Future<PayOrderModel> createRechargeOrder(
{
required String identifying,
required String type,
}) async {
final result = await HttpService.to.post(
'/v1/orders/Orders/createBeanorders',
params: {
'type': type,
'identifying': identifying,
},
);
if (result.data is! Map) return PayOrderModel();
return PayOrderModel.fromJson(result.data);
}
} }
...@@ -134,19 +134,19 @@ abstract class ShopAPI { ...@@ -134,19 +134,19 @@ abstract class ShopAPI {
} }
/// 9、获取订单状态 /// 9、获取订单状态
static Future <bool> orderStatus({ static Future <OrderStatusModel> orderStatus({
required String orderNumber, required String orderNumber,
required String receipt
}) async { }) async {
final result = await HttpService.to.post( final result = await HttpService.to.post(
'/v1/orders/Orders/getOrdersStatus', '/v1/orders/Orders/getOrdersStatus',
params: { params: {
'ordersnum':orderNumber, 'ordersnum':orderNumber,
'receipt':receipt
}, },
); );
if (result.data is Map && result.data['pay_success'] == 1){ if (result.data is! Map ) return OrderStatusModel();
return true; return OrderStatusModel.fromJson(result.data);
}
return false;
} }
......
...@@ -236,4 +236,30 @@ class PayOrderModel { ...@@ -236,4 +236,30 @@ class PayOrderModel {
return map; return map;
} }
}
/// 订单状态模型
class OrderStatusModel {
OrderStatusModel({
this.paySuccess,
this.ordersnum,});
OrderStatusModel.fromJson(dynamic json) {
paySuccess = json['pay_success'];
ordersnum = json['ordersnum'];
}
num? paySuccess;
String? ordersnum;
OrderStatusModel copyWith({ num? paySuccess,
String? ordersnum,
}) => OrderStatusModel( paySuccess: paySuccess ?? this.paySuccess,
ordersnum: ordersnum ?? this.ordersnum,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['pay_success'] = paySuccess;
map['ordersnum'] = ordersnum;
return map;
}
} }
\ No newline at end of file
...@@ -27,7 +27,7 @@ class BookDetailController extends GetxController with GetSingleTickerProviderSt ...@@ -27,7 +27,7 @@ class BookDetailController extends GetxController with GetSingleTickerProviderSt
@override @override
void onReady() { void onReady() {
_getBookDetails(); getBookDetails();
_getChapters(); _getChapters();
super.onReady(); super.onReady();
} }
...@@ -54,7 +54,7 @@ class BookDetailController extends GetxController with GetSingleTickerProviderSt ...@@ -54,7 +54,7 @@ class BookDetailController extends GetxController with GetSingleTickerProviderSt
} }
/// 获取图书详细信息 /// 获取图书详细信息
void _getBookDetails() async { void getBookDetails() async {
bookDetails = await LibraryAPI.details(bookId:bookId); bookDetails = await LibraryAPI.details(bookId:bookId);
update(); update();
} }
...@@ -73,7 +73,7 @@ class BookDetailController extends GetxController with GetSingleTickerProviderSt ...@@ -73,7 +73,7 @@ class BookDetailController extends GetxController with GetSingleTickerProviderSt
bookId: bookId, love: isCollection.toString()); bookId: bookId, love: isCollection.toString());
print('================================$result'); print('================================$result');
if (result) { if (result) {
_getBookDetails(); getBookDetails();
} }
} }
......
...@@ -124,7 +124,7 @@ class _BookDetailPageState extends State<BookDetailPage> with SingleTickerProvid ...@@ -124,7 +124,7 @@ class _BookDetailPageState extends State<BookDetailPage> with SingleTickerProvid
Gaps.hGaps10, Gaps.hGaps10,
Expanded( Expanded(
child: GestureDetector( child: GestureDetector(
onTap: (){ onTap: () async{
// context.pushNamed(Routes.creditPoints).then((value){ // context.pushNamed(Routes.creditPoints).then((value){
// print('---------------------$value'); // print('---------------------$value');
// }); // });
...@@ -143,7 +143,11 @@ class _BookDetailPageState extends State<BookDetailPage> with SingleTickerProvid ...@@ -143,7 +143,11 @@ class _BookDetailPageState extends State<BookDetailPage> with SingleTickerProvid
selected: true selected: true
); );
buy.add(model); buy.add(model);
context.pushNamed(Routes.bookPay,extra: buy);
final result = await context.pushNamed(Routes.bookPay,extra: buy);
if (result == true) {
controller.getBookDetails();
}
} }
else { else {
context.pushNamed(Routes.web); context.pushNamed(Routes.web);
......
part of book_pay; part of book_pay;
class BookPayController extends GetxController { class BookPayController extends GetxController {
final BuildContext context;
// 购物车选中的书籍列表 // 购物车选中的书籍列表
final List<CourseModel> buy; final List<CourseModel> buy;
BookPayController({required this.buy}); BookPayController({required this.buy,required this.context});
// 积分模型 // 积分模型
CreditPointModel creditPointModel = CreditPointModel(deductibleIntegral: 0); CreditPointModel creditPointModel = CreditPointModel(deductibleIntegral: 0);
// 是否展示优惠券和积分模型 // 是否展示优惠券和积分模型
...@@ -22,13 +23,14 @@ class BookPayController extends GetxController { ...@@ -22,13 +23,14 @@ class BookPayController extends GetxController {
List<PayModel> pays = Platform.isIOS ?[ List<PayModel> pays = Platform.isIOS ?[
PayModel(type: 3, name: '紫荆币', icon: 'assets/images/pay_coin.png', selected: true), PayModel(type: 3, name: '紫荆币', icon: 'assets/images/pay_coin.png', selected: true),
]:[ ]:[
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),
PayModel(type: 3, name: '紫荆币', icon: 'assets/images/pay_coin.png', selected: false), PayModel(type: 3, name: '紫荆币', icon: 'assets/images/pay_coin.png', selected: false),
]; ];
// 支付宝 // 支付宝
// Tobias tobias = Tobias(); Tobias tobias = Tobias();
// 微信
Fluwx fluwx = Fluwx(); Fluwx fluwx = Fluwx();
// 时候展示底部视图 // 时候展示底部视图
...@@ -162,11 +164,11 @@ class BookPayController extends GetxController { ...@@ -162,11 +164,11 @@ class BookPayController extends GetxController {
} }
// 支付宝 // 支付宝
if (payModel.type == 2){ if (payModel.type == 2){
// final result = await tobias.isAliPayInstalled; final result = await tobias.isAliPayInstalled;
// if(!result){ if(!result){
// Toast.show('请先安装支付宝'); Toast.show('请先安装支付宝');
// return; return;
// } }
} }
// 微信 // 微信
if (payModel.type ==1){ if (payModel.type ==1){
...@@ -213,13 +215,13 @@ class BookPayController extends GetxController { ...@@ -213,13 +215,13 @@ class BookPayController extends GetxController {
void requestAliPay(){ void requestAliPay(){
print('================================================================${payOrderModel.encryptionOrder!}'); print('================================================================${payOrderModel.encryptionOrder!}');
// tobias.pay(payOrderModel.encryptionOrder!).then((payResult){ tobias.pay(payOrderModel.encryptionOrder!).then((payResult){
// if (payResult['resultStatus'] == '9000') { if (payResult['resultStatus'] == '9000') {
// requestOrderStatus(); requestOrderStatus();
// } else { } else {
// Toast.show(payResult['memo'].toString()); Toast.show(payResult['memo'].toString());
// } }
// }); });
} }
// 微信支付 // 微信支付
...@@ -245,10 +247,14 @@ class BookPayController extends GetxController { ...@@ -245,10 +247,14 @@ class BookPayController extends GetxController {
} }
void requestOrderStatus() async { void requestOrderStatus() async {
final result = await ShopAPI.orderStatus(orderNumber: payOrderModel.ordersnum??''); final result = await ShopAPI.orderStatus(orderNumber: payOrderModel.ordersnum??'',receipt: '');
if (result){ if (result.paySuccess == 1){
Toast.show('订单支付完成'); Toast.show('订单支付完成');
if(context.mounted){
context.pop(true);
}
} }
} }
......
...@@ -16,7 +16,7 @@ class _BookPayPageState extends State<BookPayPage> { ...@@ -16,7 +16,7 @@ class _BookPayPageState extends State<BookPayPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GetBuilder<BookPayController>( return GetBuilder<BookPayController>(
init: BookPayController(buy: widget.buy), init: BookPayController(buy: widget.buy,context: context),
builder: (controller) => Stack( builder: (controller) => Stack(
children: [ children: [
Scaffold( Scaffold(
......
...@@ -15,7 +15,7 @@ class BuildPayCount extends StatelessWidget { ...@@ -15,7 +15,7 @@ class BuildPayCount extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GetBuilder<BookPayController>( return GetBuilder<BookPayController>(
init: BookPayController(buy: []), init: BookPayController(buy: [],context: context),
builder:(controller)=> Container( builder:(controller)=> Container(
padding: EdgeInsets.symmetric(horizontal: 15.w), padding: EdgeInsets.symmetric(horizontal: 15.w),
height: 55.w, height: 55.w,
......
...@@ -143,7 +143,7 @@ class BookshopController extends GetxController { ...@@ -143,7 +143,7 @@ class BookshopController extends GetxController {
} }
/// 获取课程内图书列表 /// 获取课程内图书列表
Future<void> _getCart([bool isRefresh = false]) async { Future<void> getCart([bool isRefresh = false]) async {
if (isRefresh) _page = 1; if (isRefresh) _page = 1;
// 网路请求 // 网路请求
final result = await ShopAPI.cart( final result = await ShopAPI.cart(
...@@ -163,7 +163,7 @@ class BookshopController extends GetxController { ...@@ -163,7 +163,7 @@ class BookshopController extends GetxController {
void onRefresh() async { void onRefresh() async {
try { try {
await _getCart(true); await getCart(true);
refreshController.finishRefresh(IndicatorResult.success); refreshController.finishRefresh(IndicatorResult.success);
refreshController.resetFooter(); refreshController.resetFooter();
} catch (error) { } catch (error) {
...@@ -177,7 +177,7 @@ class BookshopController extends GetxController { ...@@ -177,7 +177,7 @@ class BookshopController extends GetxController {
return; return;
} }
try { try {
await _getCart(); await getCart();
refreshController.finishLoad(); refreshController.finishLoad();
} catch (error) { } catch (error) {
refreshController.finishLoad(IndicatorResult.fail); refreshController.finishLoad(IndicatorResult.fail);
......
...@@ -50,9 +50,12 @@ class BuildCounter extends StatelessWidget { ...@@ -50,9 +50,12 @@ class BuildCounter extends StatelessWidget {
], ],
), ),
GestureDetector( GestureDetector(
onTap: (){ onTap: () async {
if (controller.num > 0){ if (controller.num > 0){
context.pushNamed(Routes.bookPay,extra: controller.buy); final result = await context.pushNamed(Routes.bookPay,extra: controller.buy);
if (result == true) {
controller.getCart();
}
} }
}, },
child: Container( child: Container(
......
...@@ -32,7 +32,9 @@ class _CoursePageState extends State<CoursePage> { ...@@ -32,7 +32,9 @@ class _CoursePageState extends State<CoursePage> {
icon: Image.asset( icon: Image.asset(
'assets/images/read_history.png', 'assets/images/read_history.png',
), ),
onPressed: () => context.pushNamed(Routes.studyHistory), onPressed: () async {
context.pushNamed(Routes.studyHistory);
},
), ),
GestureDetector( GestureDetector(
onTap: () async{ onTap: () async{
......
...@@ -30,16 +30,19 @@ class BuildBanner extends StatelessWidget { ...@@ -30,16 +30,19 @@ class BuildBanner extends StatelessWidget {
width: double.infinity, width: double.infinity,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.w), borderRadius: BorderRadius.circular(8.w),
color: Color.fromRGBO( // color: Color.fromRGBO(
random.nextInt(256), // Red // random.nextInt(256), // Red
random.nextInt(256), // Green // random.nextInt(256), // Green
random.nextInt(256), // Blue // random.nextInt(256), // Blue
1.0, // Alpha (opacity) // 1.0, // Alpha (opacity)
), // ),
), ),
child: Image.network(item.pic??''), child: ClipRRect(
borderRadius: BorderRadius.circular(8.w),
child: Image.network(item.pic??'',)
),
// child: CustomImage.asset( // child: CustomImage.asset(
// url: 'assets/images/banner.png', // url: 'assets/images/banner.png',
// width: 130.w, // width: 130.w,
......
...@@ -13,7 +13,7 @@ class CreditPointsPage extends StatelessWidget { ...@@ -13,7 +13,7 @@ class CreditPointsPage extends StatelessWidget {
return false; return false;
}, },
child: GetBuilder<BookPayController>( child: GetBuilder<BookPayController>(
init: BookPayController(buy: []), init: BookPayController(buy: [],context: context),
builder:(controller)=> Scaffold( builder:(controller)=> Scaffold(
extendBodyBehindAppBar: true, extendBodyBehindAppBar: true,
appBar: AppBar( appBar: AppBar(
......
...@@ -58,10 +58,10 @@ class ForgetPwdController extends GetxController { ...@@ -58,10 +58,10 @@ class ForgetPwdController extends GetxController {
// 定时器回调 // 定时器回调
}); });
/// 测试账号 /// 测试账号
if (kDebugMode) { // if (kDebugMode) {
phoneInput.text = '13521054068'; // phoneInput.text = '13521054068';
codeInput.text = '123456'; // codeInput.text = '123456';
} // }
super.onInit(); super.onInit();
} }
......
...@@ -76,14 +76,15 @@ class _LibraryPageState extends State<LibraryPage> { ...@@ -76,14 +76,15 @@ class _LibraryPageState extends State<LibraryPage> {
child: Expanded( child: Expanded(
child: CustomPullScrollView( child: CustomPullScrollView(
controller: controller.refreshController, controller: controller.refreshController,
// onRefresh: controller.onRefresh, onRefresh: controller.onRefresh,
onLoading: controller.onLoading, onLoading: controller.onLoading,
child: SingleChildScrollView( child: SingleChildScrollView(
child: Column( child: Column(
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
children: [ children: [
controller.ads.isNotEmpty?Container( controller.ads.isNotEmpty?Container(
color: Colors.cyan, color: Colors.transparent,
padding: EdgeInsets.symmetric(horizontal: 10.w),
child: BuildBanner(items:controller.ads) child: BuildBanner(items:controller.ads)
):const SizedBox(), ):const SizedBox(),
...@@ -136,7 +137,7 @@ class _LibraryPageState extends State<LibraryPage> { ...@@ -136,7 +137,7 @@ class _LibraryPageState extends State<LibraryPage> {
Widget _buildCategory(){ Widget _buildCategory(){
return Container( return Container(
height: 38, height: 38.w,
child: GetBuilder<LibraryController>( child: GetBuilder<LibraryController>(
init: LibraryController(), init: LibraryController(),
builder: (controller) =>ListView.builder( builder: (controller) =>ListView.builder(
......
...@@ -39,7 +39,7 @@ class LibraryCell extends StatelessWidget { ...@@ -39,7 +39,7 @@ class LibraryCell extends StatelessWidget {
Container( Container(
width: 100.w, width: 100.w,
height: 120.w, height: 120.w,
color: Colors.red, color: Colors.white,
), ),
/// 右侧 /// 右侧
Expanded( Expanded(
...@@ -89,7 +89,7 @@ class LibraryCell extends StatelessWidget { ...@@ -89,7 +89,7 @@ class LibraryCell extends StatelessWidget {
top: 0, top: 0,
bottom: 18, bottom: 18,
child: CustomCard( child: CustomCard(
width: 100, width: 100.w,
url: model.img??'', url: model.img??'',
) )
), ),
......
...@@ -87,10 +87,10 @@ class LoginController extends GetxController { ...@@ -87,10 +87,10 @@ class LoginController extends GetxController {
// 定时器回调 // 定时器回调
}); });
/// 测试账号 /// 测试账号
// if (kDebugMode) { if (kDebugMode) {
// phoneInput.text = '13521054068'; phoneInput.text = '13521054068';
// passwordInput.text = '123456'; passwordInput.text = '123456';
// } }
super.onInit(); super.onInit();
} }
......
...@@ -70,8 +70,8 @@ class MineController extends GetxController { ...@@ -70,8 +70,8 @@ class MineController extends GetxController {
ReadModel( ReadModel(
name: '订单', name: '订单',
value: userInfo.ordersNums.toString(), value: userInfo.ordersNums.toString(),
// link: Routes.order, link: Routes.order,
link: Routes.orderRefunded, // link: Routes.orderRefunded,
icon: 'assets/images/order.png') icon: 'assets/images/order.png')
]; ];
update(); update();
......
...@@ -102,7 +102,12 @@ class _MinePageState extends State<MinePage> { ...@@ -102,7 +102,12 @@ class _MinePageState extends State<MinePage> {
child: BuildBanner(items:controller.ads), child: BuildBanner(items:controller.ads),
):const SizedBox(), ):const SizedBox(),
Gaps.vGaps5, Gaps.vGaps5,
BuildAccount(items:controller.accounts,), BuildAccount(items:controller.accounts,onTap: (ReadModel model) async{
final result = await context.pushNamed(model.link??'');
if (result == true){
controller.getInfo();
}
},),
Gaps.vGaps10, Gaps.vGaps10,
Container( Container(
margin: EdgeInsets.symmetric(horizontal: AppTheme.margin), margin: EdgeInsets.symmetric(horizontal: AppTheme.margin),
......
...@@ -2,7 +2,7 @@ part of mine; ...@@ -2,7 +2,7 @@ part of mine;
class BuildAccount extends StatelessWidget { class BuildAccount extends StatelessWidget {
final List<ReadModel> items ; final List<ReadModel> items ;
final void Function()? onTap; final void Function(ReadModel model)? onTap;
const BuildAccount({ const BuildAccount({
super.key, super.key,
this.onTap, this.onTap,
...@@ -41,28 +41,35 @@ class BuildAccount extends StatelessWidget { ...@@ -41,28 +41,35 @@ class BuildAccount extends StatelessWidget {
child: GestureDetector( child: GestureDetector(
onTap: (){ onTap: (){
if (model.link != null){ if (model.link != null){
context.pushNamed(model.link!); if (model.link != Routes.love){
if (onTap !=null) onTap; context.pushNamed(model.link!);
}
else{
if (onTap !=null) onTap!(model);
}
} }
}, },
child: Column( child: Container(
children: [ color: Colors.white,
SizedBox( child: Column(
width: 25.w, children: [
height: 25.w, SizedBox(
// color: Colors.green, width: 25.w,
child: Image.asset(model.icon!), height: 25.w,
), // color: Colors.green,
Gaps.vGaps5, child: Image.asset(model.icon!),
Text(model.name,style: TextStyle(fontSize:12.w,height: 1.6.w,color: Colours.c9),), ),
items.indexOf(model) == 0?Row( Gaps.vGaps5,
mainAxisAlignment: MainAxisAlignment.center, Text(model.name,style: TextStyle(fontSize:12.w,height: 1.6.w,color: Colours.c9),),
children: [ items.indexOf(model) == 0?Row(
Text(model.value.toString(),style: TextStyle(fontSize: 16.w,height: 1.6,fontWeight: Fonts.medium,color: AppTheme.primary,),), mainAxisAlignment: MainAxisAlignment.center,
Text('张',style: TextStyle(fontSize: 12.w,height:1.6.w,color: Colours.c3),) children: [
], Text(model.value.toString(),style: TextStyle(fontSize: 16.w,height: 1.6,fontWeight: Fonts.medium,color: AppTheme.primary,),),
):Text(model.value.toString(),style: TextStyle(fontSize: 16.w,height:1.6.w,color: Colours.c3),) Text('张',style: TextStyle(fontSize: 12.w,height:1.6.w,color: Colours.c3),)
], ],
):Text(model.value.toString(),style: TextStyle(fontSize: 16.w,height:1.6.w,color: Colours.c3),)
],
),
), ),
), ),
); );
......
...@@ -68,7 +68,7 @@ class _ResetPwdPageState extends State<ResetPwdPage> { ...@@ -68,7 +68,7 @@ class _ResetPwdPageState extends State<ResetPwdPage> {
), ),
Container( Container(
margin: EdgeInsets.only(left: 5.w,top: 5.w), margin: EdgeInsets.only(left: 5.w,top: 5.w),
child: Text('密码必须是8-20个英文字母、数字或符号',style: TextStyle(fontSize: 10.w,color: Colours.c9),), child: Text('密码必须是8-20个英文字母、数字或符号(除空格)',style: TextStyle(fontSize: 10.w,color: Colours.c9),),
), ),
Gaps.vGaps40, Gaps.vGaps40,
CustomGradientButton( CustomGradientButton(
......
...@@ -21,7 +21,7 @@ class UserCoinController extends GetxController { ...@@ -21,7 +21,7 @@ class UserCoinController extends GetxController {
/// 获取紫金币记录 /// 获取紫金币记录
Future<void> _getCoin([bool isRefresh = false]) async { Future<void> getCoin([bool isRefresh = false]) async {
if (isRefresh) _page = 1; if (isRefresh) _page = 1;
// 网路请求 // 网路请求
final result = await MineAPI.coin( final result = await MineAPI.coin(
...@@ -39,7 +39,7 @@ class UserCoinController extends GetxController { ...@@ -39,7 +39,7 @@ class UserCoinController extends GetxController {
void onRefresh() async { void onRefresh() async {
try { try {
await _getCoin(true); await getCoin(true);
refreshController.finishRefresh(IndicatorResult.success); refreshController.finishRefresh(IndicatorResult.success);
refreshController.resetFooter(); refreshController.resetFooter();
} catch (error) { } catch (error) {
...@@ -53,7 +53,7 @@ class UserCoinController extends GetxController { ...@@ -53,7 +53,7 @@ class UserCoinController extends GetxController {
return; return;
} }
try { try {
await _getCoin(); await getCoin();
refreshController.finishLoad(); refreshController.finishLoad();
} catch (error) { } catch (error) {
refreshController.finishLoad(IndicatorResult.fail); refreshController.finishLoad(IndicatorResult.fail);
......
library user_coin; library user_coin;
import 'dart:core';
import 'dart:io';
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/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_book/widgets/index.dart'; import 'package:flutter_book/widgets/index.dart';
import 'package:flutter_inapp_purchase/flutter_inapp_purchase.dart';
import 'package:flutter_inapp_purchase/modules.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:fluwx/fluwx.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tobias/tobias.dart';
import '../../apis/index.dart'; import '../../apis/index.dart';
import '../../models/index.dart'; import '../../models/index.dart';
import '../../services/index.dart';
import '../user_coin_recharge/index.dart'; import '../user_coin_recharge/index.dart';
part 'view.dart'; part 'view.dart';
......
...@@ -24,10 +24,10 @@ class _UserCoinPageState extends State<UserCoinPage> { ...@@ -24,10 +24,10 @@ class _UserCoinPageState extends State<UserCoinPage> {
borderRadius: BorderRadius.vertical(top: Radius.circular(8.w)), borderRadius: BorderRadius.vertical(top: Radius.circular(8.w)),
), ),
builder: (BuildContext context) { builder: (BuildContext context) {
return CoinRechargePage(); return const CoinRechargePage();
}, },
).then((value) { ).then((value) {
print('================================================================'); controller.getCoin();
}); });
}, },
child: Text('充值',style: TextStyle(color: Colours.c3,fontSize: 14.w,height: 1.5,fontWeight: Fonts.medium),) child: Text('充值',style: TextStyle(color: Colours.c3,fontSize: 14.w,height: 1.5,fontWeight: Fonts.medium),)
......
part of recharge; part of recharge;
class CoinRechargeController extends GetxController { class CoinRechargeController extends GetxController {
final BuildContext context;
CoinRechargeController({required this.context});
dynamic _purchaseUpdatedSubscription;
dynamic _purchaseErrorSubscription;
dynamic _connectionSubscription;
PurchasedItem? _resultItem;
List<IAPItem> _items = [];
List<PurchasedItem> _purchases = [];
///未完成的订单
List<PurchasedItem> _pendingPurchases = [];
// 支付宝
Tobias tobias = Tobias();
// 微信
Fluwx fluwx = Fluwx();
// 创建订单模型
late PayOrderModel payOrderModel;
List<PayModel> pays = Platform.isIOS ?[ List<PayModel> pays = Platform.isIOS ?[
]:[ ]:[
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 = []; List<CoinModel> data = [];
...@@ -16,12 +36,36 @@ class CoinRechargeController extends GetxController { ...@@ -16,12 +36,36 @@ class CoinRechargeController extends GetxController {
late PayModel _payModel = pays.first; late PayModel _payModel = pays.first;
PayModel get payModel => _payModel; PayModel get payModel => _payModel;
@override
void onInit() {
initPlatformState();
_getPendingPurchase();
super.onInit();
}
@override @override
void onReady() { void onReady() {
_getlist(); _getlist();
super.onReady(); super.onReady();
} }
@override
void onClose() {
if (_connectionSubscription != null) {
_connectionSubscription.cancel();
_connectionSubscription = null;
}
if (_purchaseUpdatedSubscription != null) {
_purchaseUpdatedSubscription.cancel();
_purchaseUpdatedSubscription = null;
}
if (_purchaseErrorSubscription != null) {
_purchaseErrorSubscription.cancel();
_purchaseErrorSubscription = null;
}
super.onClose();
}
void setPayModel(PayModel payModel){ void setPayModel(PayModel payModel){
for (PayModel model in pays) { for (PayModel model in pays) {
...@@ -45,7 +89,7 @@ class CoinRechargeController extends GetxController { ...@@ -45,7 +89,7 @@ class CoinRechargeController extends GetxController {
} }
/// 获取充值列表
void _getlist()async{ void _getlist()async{
String type = ''; String type = '';
if(Platform.isIOS){ if(Platform.isIOS){
...@@ -56,8 +100,199 @@ class CoinRechargeController extends GetxController { ...@@ -56,8 +100,199 @@ class CoinRechargeController extends GetxController {
} }
final result = await MineAPI.coinsRechargeList(type: type); final result = await MineAPI.coinsRechargeList(type: type);
data = result; data = result;
if(Platform.isIOS){
_getProduct();
}
update(); update();
} }
Future<void> initPlatformState() async{
var result = await FlutterInappPurchase.instance.initialize();
print('--------------initPlatformState-------------------------$result');
_connectionSubscription = FlutterInappPurchase.connectionUpdated.listen((connected) {
print('connected: $connected');
});
_purchaseUpdatedSubscription = FlutterInappPurchase.purchaseUpdated.listen((productItem) {
CustomToast.dismiss();
if(productItem != null){
_resultItem = productItem;
_requestOrderStatus();
}
});
_purchaseErrorSubscription = FlutterInappPurchase.purchaseError.listen((purchaseError) {
CustomToast.dismiss();
Toast.show(purchaseError!.message.toString());
});
}
/// 获取商品列表
Future _getProduct() async {
List<String> productList = data
.where((coinModel) => coinModel.identifying != null)
.map((coinModel) => coinModel.identifying!)
.toList();
print('-------------productList-------------------$productList');
List<IAPItem> items = await FlutterInappPurchase.instance.getProducts(productList);
for (var item in items) {
_items.add(item);
}
print('-------------_items-------------------$items');
_items = items;
_purchases = [];
// update();
}
/// 创建订单
void createRechargeOrder() async {
String type = '';
if(Platform.isIOS){
type = '3';
}
else{
type = payModel.type.toString();
}
final result = await MineAPI.createRechargeOrder(identifying: rechargeModel.identifying??'', type: type);
print('-----------------------------------${result.ordersnum}--------------------------------${result.msg}');
payOrderModel = result;
// 创建订单成功开启支付流程
if (payOrderModel.ordersnum !=null){
if(payOrderModel.ordersnum!.isNotEmpty){
// 苹果
if(Platform.isIOS){
// 发起苹果支付
IAPItem targetItem = _items.firstWhere(
(item) => item.productId == rechargeModel.identifying,
);
_requestPurchase(targetItem);
}
// 安卓
else if(Platform.isAndroid){
// 发起支付宝支付
if (payModel.type == 2){
requestAliPay();
}
else if (payModel.type == 1){
requestWechat();
}
}
}
}
}
/// 获取后台关于当前单号的结算结果
void _requestOrderStatus() async {
final result = await ShopAPI.orderStatus(orderNumber: payOrderModel.ordersnum??'',receipt:_resultItem != null?_resultItem!.transactionReceipt.toString():'');
// 查询订单支付成功
if (result.paySuccess == 1){
Toast.show('购买紫荆币成功');
if(context.mounted){
context.pop(true);
}
if (Platform.isIOS){
// 清除
if (StorageService.to.getObject(kFailOrder) != null){
List<Map<String,String>> failOrderList = StorageService.to.getObject(kFailOrder) as List<Map<String, String>>;
List<Map<String,String>> temp = [];
temp.addAll(failOrderList);
for (var element in failOrderList) {
if(element['orderNum'] == result.ordersnum){
temp.remove(element);
}
}
StorageService.to.setObject(kFailOrder, temp);
}
FlutterInappPurchase.instance.finishTransactionIOS(_resultItem!.transactionId!);
}
}
// 查询订单支付失败
else {
Toast.show('购买紫荆币失败');
if(Platform.isIOS){
// 保存未支付的订单
Map<String,String> failOrder = {
'orderNum':payOrderModel.ordersnum??'',
'transactionReceipt':_resultItem!.transactionReceipt.toString(),
'transactionId':_resultItem!.transactionId.toString()
};
List<Map> failOrderList = [];
failOrderList.add(failOrder);
StorageService.to.setObject(kFailOrder, failOrderList);
}
else {
}
}
}
/// 苹果支付
void _requestPurchase(IAPItem item) {
CustomToast.loading();
FlutterInappPurchase.instance
.requestPurchase(item.productId!);
}
/// 支付宝支付
void requestAliPay(){
tobias.pay(payOrderModel.encryptionOrder!).then((payResult){
if (payResult['resultStatus'] == '9000') {
_requestOrderStatus();
} else {
Toast.show(payResult['memo'].toString());
}
});
}
/// 微信支付
void requestWechat(){
Payment payment = Payment(
appId: payOrderModel.appid??'',
partnerId: payOrderModel.partnerid??'',
prepayId: payOrderModel.prepayid??'',
packageValue: payOrderModel.package??'',
nonceStr: payOrderModel.noncestr??'',
timestamp: payOrderModel.timestamp!.toInt(),
sign: payOrderModel.sign??''
);
fluwx.pay(which: payment);
fluwx.addSubscriber((response) {
if (response.errCode == 0) {
_requestOrderStatus();
}
else{
Toast.show('${response.errStr}');
}
});
}
///获取未完成的购买
Future _getPendingPurchase() async {
List<PurchasedItem>? items = await FlutterInappPurchase.instance.getPurchaseHistory();
for (var item in items!) {
_pendingPurchases.add(item);
}
if(StorageService.to.getObject(kFailOrder) !=null){
List<Map<String,String>> failOrderList = StorageService.to.getObject(kFailOrder) as List<Map<String, String>>;
for (var item in _pendingPurchases) {
for (var element in failOrderList) {
if(element['transactionId'] == item.transactionId){
_requestOrderStatus();
}
}
}
}
}
} }
\ No newline at end of file
library recharge; library recharge;
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_book/apis/index.dart'; import 'package:flutter_book/apis/index.dart';
import 'package:flutter_book/models/index.dart'; import 'package:flutter_book/models/index.dart';
import 'package:flutter_book/theme.dart'; import 'package:flutter_book/theme.dart';
import 'package:flutter_inapp_purchase/flutter_inapp_purchase.dart';
import 'package:flutter_inapp_purchase/modules.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:fluwx/fluwx.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 'package:go_router/go_router.dart';
import 'package:tobias/tobias.dart';
import '../../services/index.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';
import 'dart:io'; import 'dart:io';
import '../user_coin/index.dart';
part 'view.dart'; part 'view.dart';
part 'controller.dart'; part 'controller.dart';
\ No newline at end of file
...@@ -9,11 +9,11 @@ class CoinRechargePage extends StatefulWidget { ...@@ -9,11 +9,11 @@ class CoinRechargePage extends StatefulWidget {
State<CoinRechargePage> createState() => _CoinRechargePageState(); State<CoinRechargePage> createState() => _CoinRechargePageState();
} }
class _CoinRechargePageState extends State<CoinRechargePage> { class _CoinRechargePageState extends State<CoinRechargePage> with AutomaticKeepAliveClientMixin {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GetBuilder<CoinRechargeController>( return GetBuilder<CoinRechargeController>(
init: CoinRechargeController(), init: CoinRechargeController(context: context),
builder:(controller) => Column( builder:(controller) => Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
...@@ -63,7 +63,7 @@ class _CoinRechargePageState extends State<CoinRechargePage> { ...@@ -63,7 +63,7 @@ class _CoinRechargePageState extends State<CoinRechargePage> {
text: '立即充值${controller.rechargeModel.priceName??''}', text: '立即充值${controller.rechargeModel.priceName??''}',
isEnabled: true, isEnabled: true,
onPressed: () { onPressed: () {
// context.goNamed(Routes.login); controller.createRechargeOrder();
}, },
), ),
), ),
...@@ -133,4 +133,8 @@ class _CoinRechargePageState extends State<CoinRechargePage> { ...@@ -133,4 +133,8 @@ class _CoinRechargePageState extends State<CoinRechargePage> {
itemCount: controller.pays.length, itemCount: controller.pays.length,
); );
} }
@override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
} }
...@@ -8,7 +8,7 @@ class UserInfoController extends GetxController { ...@@ -8,7 +8,7 @@ class UserInfoController extends GetxController {
void upload({ void upload({
required String path required String path
}) async { }) async {
String result = await CommonAPI.upload(path:path); String result = await CommonAPI.upload(path:path,fileTypes: 'user');
_changeInfo(result); _changeInfo(result);
} }
......
...@@ -49,9 +49,6 @@ class _UserInfoPageState extends State<UserInfoPage> { ...@@ -49,9 +49,6 @@ class _UserInfoPageState extends State<UserInfoPage> {
onTap: () async { onTap: () async {
final assets = await AssetsPicker.image( final assets = await AssetsPicker.image(
context: context, context: context,
source: ImageSource.gallery,
maxWidth: 512.w,
maxHeight: 512.w,
); );
controller.upload(path: assets!.path); controller.upload(path: assets!.path);
}, },
......
...@@ -4,6 +4,13 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -4,6 +4,13 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
// 目录 // 目录
List <ChapterModel> chapters = []; List <ChapterModel> chapters = [];
List <ToolModel> tools = [
ToolModel(tag: 0,name: '目录',selected: false,icon: 'assets/images/category_unselect.png',activeIcon: 'assets/images/category_select.png'),
ToolModel(tag: 1,name: '笔记',selected: false,icon: 'assets/images/note_unselect.png',activeIcon:'assets/images/note_select.png'),
ToolModel(tag: 2,name: '讨论',selected: false,icon: 'assets/images/discuss_unselect.png',activeIcon:'assets/images/discuss_select.png'),
];
late ToolModel toolModel = tools.first;
// late final PageController pageController; // late final PageController pageController;
// //
...@@ -33,6 +40,22 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -33,6 +40,22 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
} }
void chooseTool(ToolModel selectedModel){
for (var model in tools) {
// 如果当前遍历到的工具是选中的,并且不是点击的工具,则取消选中
if (model.selected && model != selectedModel) {
model.selected = false;
}
// 如果当前遍历到的工具是点击的工具,切换选中状态
else if (model == selectedModel) {
model.selected = !model.selected;
}
}
toolModel = selectedModel;
update();
}
AnimationController get controller => _controller; AnimationController get controller => _controller;
...@@ -88,4 +111,13 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide ...@@ -88,4 +111,13 @@ class ReadController extends FullLifeCycleController with GetSingleTickerProvide
chapters = await LibraryAPI.chapters(bookId: '110'); chapters = await LibraryAPI.chapters(bookId: '110');
update(); update();
} }
}
class ToolModel {
ToolModel({required this.tag, required this.selected, required this.name,required this.icon,required this.activeIcon});
int tag;
String name;
bool selected;
String icon;
String activeIcon;
} }
\ No newline at end of file
...@@ -4,6 +4,7 @@ library web; ...@@ -4,6 +4,7 @@ library web;
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/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_book/theme.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.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';
......
...@@ -69,7 +69,7 @@ class _ReadPageState extends State<ReadPage> { ...@@ -69,7 +69,7 @@ class _ReadPageState extends State<ReadPage> {
right: 0, right: 0,
top: 0, top: 0,
bottom: 49 + MediaQuery.of(context).viewInsets.bottom, bottom: 49 + MediaQuery.of(context).viewInsets.bottom,
child: _showContent(readController,currentIndex) child: _showContent(readController,readController.toolModel)
), ),
AnimatedPositioned( AnimatedPositioned(
duration: readController.controller.duration!, duration: readController.controller.duration!,
...@@ -81,44 +81,7 @@ class _ReadPageState extends State<ReadPage> { ...@@ -81,44 +81,7 @@ class _ReadPageState extends State<ReadPage> {
child: Container( child: Container(
color: Colors.limeAccent, color: Colors.limeAccent,
alignment: Alignment.center, alignment: Alignment.center,
child: BottomNavigationBar( child: _createToolBar(readController)
currentIndex: currentIndex,
onTap: (index){
setState(() {
currentIndex = index;
});
// _showBottomSheet(context, index);
},
items: [
BottomNavigationBarItem(
label: '目录',
icon: Image.asset(
'assets/images/category_unselect.png',
),
activeIcon: Image.asset(
'assets/images/category_select.png',
),
),
BottomNavigationBarItem(
label: '笔记',
icon: Image.asset(
'assets/images/note_unselect.png',
),
activeIcon: Image.asset(
'assets/images/note_select.png',
)
),
BottomNavigationBarItem(
label: '讨论',
icon: Image.asset(
'assets/images/discuss_unselect.png',
),
activeIcon: Image.asset(
'assets/images/discuss_select.png',
)
),
],
)
), ),
), ),
...@@ -129,50 +92,91 @@ class _ReadPageState extends State<ReadPage> { ...@@ -129,50 +92,91 @@ class _ReadPageState extends State<ReadPage> {
); );
} }
Widget _showContent(ReadController controller,int index) {
print('++++++++++++++++++++++++$index'); Widget _createToolBar(ReadController controller){
return Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: controller.tools.map((model){
return Expanded(
child: GestureDetector(
onTap: (){
controller.chooseTool(model);
},
child: Container(
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
SizedBox(
width: 17,
height: 17,
child: Image.asset(model.selected?model.activeIcon:model.icon)
),
// SizedBox(height: 2.5.w,),
model.selected?Text(model.name,style: TextStyle(fontSize: 10.w,height: 1.4,fontWeight: Fonts.medium,color: AppTheme.primary),)
:Text(model.name,style: TextStyle(fontSize: 10.w,height: 1.4,fontWeight: Fonts.medium,color: Colours.c6))
],
),
),
),
);
}).toList()
),
);
}
Widget _showContent(ReadController controller,ToolModel model) {
print('++++++++++++++++++++++++${model.tag}');
if (controller.show){ if (controller.show){
if (index == 0){ if (model.tag == 0){
return Container( return model.selected? Container(
color: Color(0xFF000000).withOpacity(0.5), color: Color(0xFF000000).withOpacity(0.5),
padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.2), padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.2),
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.only(topRight: Radius.circular(8.w),topLeft: Radius.circular(8.w)), borderRadius: BorderRadius.only(topRight: Radius.circular(8.w),topLeft: Radius.circular(8.w)),
child: Container( child: Container(
color: Colors.white, color: Colors.white,
child: ReadCategoryPage(controller: controller,), child: ReadCategoryPage(controller: controller,onTap: (){
controller.chooseTool(model);
},),
), ),
), ),
// child: ReadCategoryPage(), // child: ReadCategoryPage(),
); ):const SizedBox();
} }
else if (index == 1){ else if (model.tag == 1){
return Container( return model.selected? Container(
color: Color(0xFF000000).withOpacity(0.5), color: Color(0xFF000000).withOpacity(0.5),
padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.2), padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.2),
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.only(topRight: Radius.circular(8.w),topLeft: Radius.circular(8.w)), borderRadius: BorderRadius.only(topRight: Radius.circular(8.w),topLeft: Radius.circular(8.w)),
child: Container( child: Container(
color: Colors.white, color: Colors.white,
child: ReadNotePage(), child: ReadNotePage(onTap: (){
controller.chooseTool(model);
},),
), ),
), ),
// child: ReadCategoryPage(), // child: ReadCategoryPage(),
); ):const SizedBox();
} }
else if (index == 2){ else if (model.tag == 2){
return Container( return model.selected? Container(
color: Color(0xFF000000).withOpacity(0.5), color: Color(0xFF000000).withOpacity(0.5),
padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.2), padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.2),
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.only(topRight: Radius.circular(8.w),topLeft: Radius.circular(8.w)), borderRadius: BorderRadius.only(topRight: Radius.circular(8.w),topLeft: Radius.circular(8.w)),
child: Container( child: Container(
color: Colors.white, color: Colors.white,
child: ReadNotePage(), child: ReadDiscussPage(onTap: (){
controller.chooseTool(model);
},),
), ),
), ),
// child: ReadCategoryPage(), // child: ReadCategoryPage(),
); ):const SizedBox();
} }
} }
return const SizedBox(); return const SizedBox();
......
...@@ -2,9 +2,11 @@ part of web; ...@@ -2,9 +2,11 @@ part of web;
class ReadCategoryPage extends StatefulWidget { class ReadCategoryPage extends StatefulWidget {
final ReadController controller; final ReadController controller;
final void Function()? onTap;
const ReadCategoryPage({ const ReadCategoryPage({
Key? key, Key? key,
required this.controller, required this.controller,
required this.onTap,
}) : super(key: key); }) : super(key: key);
@override @override
...@@ -24,7 +26,10 @@ class _ReadCategoryPageState extends State<ReadCategoryPage> { ...@@ -24,7 +26,10 @@ class _ReadCategoryPageState extends State<ReadCategoryPage> {
children: [ children: [
Container( Container(
margin: EdgeInsets.only(left: 15.w,right: 15.w,top: 15.w,bottom: 15.w), margin: EdgeInsets.only(left: 15.w,right: 15.w,top: 15.w,bottom: 15.w),
child: Image.asset('assets/images/close.png') child: GestureDetector(
onTap:widget.onTap,
child: Image.asset('assets/images/close.png'),
)
), ),
Container( Container(
margin: EdgeInsets.only(left: 15.w,right: 15.w,), margin: EdgeInsets.only(left: 15.w,right: 15.w,),
...@@ -45,7 +50,7 @@ class _ReadCategoryPageState extends State<ReadCategoryPage> { ...@@ -45,7 +50,7 @@ class _ReadCategoryPageState extends State<ReadCategoryPage> {
child: CustomInputSearch( child: CustomInputSearch(
controller: searchController, controller: searchController,
readOnly: false, readOnly: false,
hintText: '请输入书籍名称', hintText: '请输入书籍名称分类',
onTap: () { onTap: () {
// context.pushNamed(Routes.msgs); // context.pushNamed(Routes.msgs);
}, },
......
part of web; part of web;
class ReadDiscussPage extends StatefulWidget { class ReadDiscussPage extends StatefulWidget {
const ReadDiscussPage({Key? key}) : super(key: key); final void Function()? onTap;
const ReadDiscussPage({
Key? key,
required this.onTap,
}) : super(key: key);
@override @override
State<ReadDiscussPage> createState() => _ReadDiscussPageState(); State<ReadDiscussPage> createState() => _ReadDiscussPageState();
...@@ -20,7 +24,10 @@ class _ReadDiscussPageState extends State<ReadDiscussPage> { ...@@ -20,7 +24,10 @@ class _ReadDiscussPageState extends State<ReadDiscussPage> {
children: [ children: [
Container( Container(
margin: EdgeInsets.only(left: 15.w,right: 15.w,top: 15.w,bottom: 15.w), margin: EdgeInsets.only(left: 15.w,right: 15.w,top: 15.w,bottom: 15.w),
child: Image.asset('assets/images/close.png') child: GestureDetector(
onTap: widget.onTap,
child: Image.asset('assets/images/close.png')
)
), ),
Container( Container(
margin: EdgeInsets.only(left: 15.w,right: 15.w,), margin: EdgeInsets.only(left: 15.w,right: 15.w,),
...@@ -41,7 +48,7 @@ class _ReadDiscussPageState extends State<ReadDiscussPage> { ...@@ -41,7 +48,7 @@ class _ReadDiscussPageState extends State<ReadDiscussPage> {
child: CustomInputSearch( child: CustomInputSearch(
controller: searchController, controller: searchController,
readOnly: false, readOnly: false,
hintText: '请输入书籍名称', hintText: '请输入书籍名称讨论',
onTap: () { onTap: () {
// context.pushNamed(Routes.msgs); // context.pushNamed(Routes.msgs);
}, },
...@@ -52,12 +59,14 @@ class _ReadDiscussPageState extends State<ReadDiscussPage> { ...@@ -52,12 +59,14 @@ class _ReadDiscussPageState extends State<ReadDiscussPage> {
), ),
), ),
BuildBook(), BuildBook(),
ListView.builder( Expanded(
itemBuilder: (BuildContext context,int index){ child: ListView.builder(
DiscussModel model = controller.discuss[index]; itemBuilder: (BuildContext context,int index){
return BuildDiscuss(model: model,); DiscussModel model = controller.discuss[index];
}, return BuildDiscuss(model: model,);
itemCount: controller.discuss.length, },
itemCount: controller.discuss.length,
),
) )
], ],
......
part of web; part of web;
class ReadNotePage extends StatefulWidget { class ReadNotePage extends StatefulWidget {
const ReadNotePage({Key? key}) : super(key: key); final void Function()? onTap;
const ReadNotePage({
Key? key,
required this.onTap,
}) : super(key: key);
@override @override
State<ReadNotePage> createState() => _ReadNotePageState(); State<ReadNotePage> createState() => _ReadNotePageState();
...@@ -18,7 +22,10 @@ class _ReadNotePageState extends State<ReadNotePage> { ...@@ -18,7 +22,10 @@ class _ReadNotePageState extends State<ReadNotePage> {
children: [ children: [
Container( Container(
margin: EdgeInsets.only(left: 15.w,right: 15.w,top: 15.w,bottom: 15.w), margin: EdgeInsets.only(left: 15.w,right: 15.w,top: 15.w,bottom: 15.w),
child: Image.asset('assets/images/close.png') child: GestureDetector(
onTap: widget.onTap,
child: Image.asset('assets/images/close.png')
)
), ),
Container( Container(
margin: EdgeInsets.only(left: 15.w,right: 15.w,), margin: EdgeInsets.only(left: 15.w,right: 15.w,),
...@@ -39,7 +46,7 @@ class _ReadNotePageState extends State<ReadNotePage> { ...@@ -39,7 +46,7 @@ class _ReadNotePageState extends State<ReadNotePage> {
child: CustomInputSearch( child: CustomInputSearch(
controller: searchController, controller: searchController,
readOnly: false, readOnly: false,
hintText: '请输入书籍名称', hintText: '请输入书籍名称笔记',
onTap: () { onTap: () {
// context.pushNamed(Routes.msgs); // context.pushNamed(Routes.msgs);
}, },
......
...@@ -109,6 +109,7 @@ class HttpService extends GetxService { ...@@ -109,6 +109,7 @@ class HttpService extends GetxService {
Future<ResponseModel> upload( Future<ResponseModel> upload(
String url, { String url, {
required String path, required String path,
required fileTypes,
Options? options, Options? options,
CancelToken? cancelToken, CancelToken? cancelToken,
bool excludeToken = false, bool excludeToken = false,
...@@ -118,7 +119,10 @@ class HttpService extends GetxService { ...@@ -118,7 +119,10 @@ class HttpService extends GetxService {
requestOptions.headers = _getHeaders(excludeToken: excludeToken,url:url); requestOptions.headers = _getHeaders(excludeToken: excludeToken,url:url);
final name = path.substring(path.lastIndexOf('/') + 1,path.length); final name = path.substring(path.lastIndexOf('/') + 1,path.length);
final image = await MultipartFile.fromFile(path, filename: name); final image = await MultipartFile.fromFile(path, filename: name);
final formData = FormData.fromMap({'files':image}); final formData = FormData.fromMap({
'files':image,
'file_types':fileTypes
});
final response = await _dio.post( final response = await _dio.post(
url, url,
data:formData, data:formData,
...@@ -162,7 +166,7 @@ class HttpService extends GetxService { ...@@ -162,7 +166,7 @@ class HttpService extends GetxService {
class _RequestInterceptor extends Interceptor { class _RequestInterceptor extends Interceptor {
@override @override
void onResponse(Response response, ResponseInterceptorHandler handler) { void onResponse(Response response, ResponseInterceptorHandler handler) async {
if (response.data['code'] != 200) { if (response.data['code'] != 200) {
handler.reject( handler.reject(
DioException( DioException(
...@@ -172,7 +176,7 @@ class _RequestInterceptor extends Interceptor { ...@@ -172,7 +176,7 @@ class _RequestInterceptor extends Interceptor {
), ),
true, true,
); );
} else { }else {
super.onResponse(response, handler); super.onResponse(response, handler);
} }
} }
...@@ -198,7 +202,6 @@ class _RequestInterceptor extends Interceptor { ...@@ -198,7 +202,6 @@ class _RequestInterceptor extends Interceptor {
final statusCode = response?.statusCode; final statusCode = response?.statusCode;
print('************* ${response?.data}'); print('************* ${response?.data}');
// Console.log(response?.data); // Console.log(response?.data);
final code = int.tryParse(response?.data['code']?.toString() ?? '');
var msg = '服务器错误'; var msg = '服务器错误';
switch (statusCode) { switch (statusCode) {
case 401: case 401:
...@@ -233,20 +236,23 @@ class _RequestInterceptor extends Interceptor { ...@@ -233,20 +236,23 @@ class _RequestInterceptor extends Interceptor {
break; break;
case 404: case 404:
msg = '$statusCode - Server not found'; msg = '$statusCode - Server not found';
CustomToast.fail(msg);
break; break;
case 500: case 500:
msg = '$statusCode - Server error'; msg = '$statusCode - Server error';
CustomToast.fail(msg);
break; break;
case 502: case 502:
msg = '$statusCode - Bad gateway'; msg = '$statusCode - Bad gateway';
CustomToast.fail(msg);
break; break;
default: default:
// if (code == 901) UserStore.to.logout(); // if (code == 901) UserStore.to.logout();
// msg = response?.data?['msg']?.toString() ?? msg; // msg = response?.data?['msg']?.toString() ?? msg;
msg = response?.data?['message']?.toString() ?? msg; msg = response?.data?['message']?.toString() ?? msg;
CustomToast.fail(msg);
break; break;
} }
CustomToast.fail(msg);
break; break;
case DioExceptionType.cancel: case DioExceptionType.cancel:
Console.log('请求取消'); Console.log('请求取消');
...@@ -262,10 +268,14 @@ class _RequestInterceptor extends Interceptor { ...@@ -262,10 +268,14 @@ class _RequestInterceptor extends Interceptor {
} }
Future<String?> refreshToken() async { Future<String?> refreshToken() async {
final result = await HttpService.to.post( final result = await HttpService.to.post(
'/v1/members/login/getToken', '/v1/members/login/getToken',
params: {
'access_token':UserStore.to.accessToken
}
); );
if (result.data is! Map) { if (result.data is Map) {
await Future.wait([ await Future.wait([
UserStore.to.setToken(result.data['token']), UserStore.to.setToken(result.data['token']),
UserStore.to.setAccessToken(result.data['access_token']), UserStore.to.setAccessToken(result.data['access_token']),
......
library services; library services;
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter_book/store/index.dart'; import 'package:flutter_book/store/index.dart';
......
...@@ -26,6 +26,11 @@ class StorageService extends GetxService { ...@@ -26,6 +26,11 @@ class StorageService extends GetxService {
return await _prefs.setStringList(key, value); return await _prefs.setStringList(key, value);
} }
///存储Object
Future<bool>? setObject(String key, Object value) {
return _prefs.setString(key, json.encode(value));
}
///获取字符串 ///获取字符串
String getString(String key) { String getString(String key) {
return _prefs.getString(key) ?? ''; return _prefs.getString(key) ?? '';
...@@ -40,6 +45,11 @@ class StorageService extends GetxService { ...@@ -40,6 +45,11 @@ class StorageService extends GetxService {
List<String> getList(String key) { List<String> getList(String key) {
return _prefs.getStringList(key) ?? []; return _prefs.getStringList(key) ?? [];
} }
/// 获取object
Map? getObject(String key) {
String? data = _prefs.getString(key);
return (data == null || data.isEmpty) ? null : json.decode(data);
}
///移除key ///移除key
Future<bool> remove(String key) async { Future<bool> remove(String key) async {
......
...@@ -16,6 +16,12 @@ abstract class Access { ...@@ -16,6 +16,12 @@ abstract class Access {
return false; return false;
} }
/// 相机权限
static Future<bool> camera() async {
final result = await [Permission.camera].request();
return result[Permission.camera] == PermissionStatus.granted;
}
/// 打开设置 /// 打开设置
static Future<void> setting() async => await openAppSettings(); static Future<void> setting() async => await openAppSettings();
......
...@@ -3,6 +3,7 @@ part of utils; ...@@ -3,6 +3,7 @@ part of utils;
abstract class AssetsPicker { abstract class AssetsPicker {
static final ImagePicker _imagePicker = ImagePicker(); static final ImagePicker _imagePicker = ImagePicker();
/// 获取图库
static Future<XFile?> image({ static Future<XFile?> image({
required BuildContext context, required BuildContext context,
ImageSource source = ImageSource.gallery, ImageSource source = ImageSource.gallery,
...@@ -24,4 +25,27 @@ abstract class AssetsPicker { ...@@ -24,4 +25,27 @@ abstract class AssetsPicker {
maxHeight: maxHeight, maxHeight: maxHeight,
); );
} }
/// 拍照
static Future<XFile?> camera({
required BuildContext context,
ImageSource source = ImageSource.camera,
double maxWidth = 512,
double maxHeight = 512,
}) async {
if (!(await Access.photos())) {
if (context.mounted) {
CustomDialog.showAccess(
context: context,
content: const Text('Requires access to your photo gallery'),
);
}
return null;
}
return _imagePicker.pickImage(
source: source,
maxWidth: maxWidth,
maxHeight: maxHeight,
);
}
} }
...@@ -2,14 +2,15 @@ part of utils; ...@@ -2,14 +2,15 @@ part of utils;
// 服务器地址 // 服务器地址
// const String kServerUrl = 'https://app.vning.com'; // const String kServerUrl = 'https://app.vning.com';
const String kServerUrl = 'http://192.168.11.88:81'; // const String kServerUrl = 'http://192.168.11.88:81';
const String kServerUrl = 'http://1507.superge.cn:81';
const String kLocalToken = 'local_token'; const String kLocalToken = 'local_token';
const String kLocalAccessToken = 'local_access_token'; const String kLocalAccessToken = 'local_access_token';
const String kLocalAccount = 'local_account'; const String kLocalAccount = 'local_account';
const String kLocalPassword = 'local_password'; const String kLocalPassword = 'local_password';
const String kLocalUserInfo = 'local_user_info'; const String kLocalUserInfo = 'local_user_info';
const String kSearchHistory = 'search_history'; const String kSearchHistory = 'search_history';
const String kFailOrder = 'failOrder';
......
...@@ -65,6 +65,7 @@ class Gaps { ...@@ -65,6 +65,7 @@ class Gaps {
class Fonts { class Fonts {
static const medium = FontWeight.w500; static const medium = FontWeight.w500;
static const regular = FontWeight.w400;
static const bold = FontWeight.bold; static const bold = FontWeight.bold;
static const boldSemi = FontWeight.w600; static const boldSemi = FontWeight.w600;
} }
......
...@@ -34,7 +34,7 @@ class CustomCard extends StatelessWidget { ...@@ -34,7 +34,7 @@ class CustomCard extends StatelessWidget {
width: width, width: width,
child: Container( child: Container(
padding: const EdgeInsets.all(1), padding: const EdgeInsets.all(1),
child: CustomImage.network(url: url), child: CustomImage.network(url: url,placeholder: Image.asset('assets/images/book_placeholder.png'),),
), ),
); );
} }
......
...@@ -82,6 +82,9 @@ class CustomDialog extends StatelessWidget { ...@@ -82,6 +82,9 @@ class CustomDialog extends StatelessWidget {
)); ));
} }
return Dialog( return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.w), // 调整这里的数值以设置圆角大小
),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
......
...@@ -190,6 +190,14 @@ packages: ...@@ -190,6 +190,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.5" version: "3.0.5"
flutter_inapp_purchase:
dependency: "direct main"
description:
name: flutter_inapp_purchase
sha256: d67544e703439feefe91cab9cb4920cffc0f1576f7ce51a78e3a0a3c5f7d3f1e
url: "https://pub.flutter-io.cn"
source: hosted
version: "5.6.1"
flutter_inappwebview: flutter_inappwebview:
dependency: "direct main" dependency: "direct main"
description: description:
......
...@@ -100,7 +100,9 @@ dependencies: ...@@ -100,7 +100,9 @@ dependencies:
# 能指定滑动位置的listView # 能指定滑动位置的listView
azlistview: ^2.0.0 azlistview: ^2.0.0
# 支付宝 # 支付宝
# tobias: ^3.3.0 tobias: ^3.3.0
# 内购
flutter_inapp_purchase: ^5.6.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论