Browse Source
抬头信息页面ui绘制与交互,接口数据对接; 填写发票信息页面ui绘制与交互,接口数据对接; 我的页面新增发票助手; 订单列表因app订单原因,不单独显示开票选项; 开票管理接口数据对接,交互流程调试; 开票流程交互调试更改; 新增发票详情页面; pdf显示处理,新增依赖(flutter_pdfview); 新增发票详情接口;dart3
wurong
5 months ago
19 changed files with 7812 additions and 121 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,286 @@
|
||||
/// records : [{"id":"1820725763083599872","createTime":"2024-08-06 15:37:04","createUser":"1379254113602109440","updateTime":"2024-08-06 15:37:04","updateUser":"1379254113602109440","userId":"1379254113602109440","isDefault":1,"type":"PERSONAL","name":"哈哈","taxId":"","companyAddr":"","companyPhone":"","bank":"","bankNumber":"","isDelete":0},{"id":"1818128371540819968","createTime":"2024-07-30 11:35:58","createUser":"1379254113602109440","updateTime":"2024-07-30 11:35:58","updateUser":"1379254113602109440","userId":"1379254113602109440","isDefault":1,"type":"COMPANY","name":"彗星","taxId":"123568986457","companyAddr":"","companyPhone":"","bank":"","bankNumber":"","isDelete":0}] |
||||
/// total : "2" |
||||
/// size : "50" |
||||
/// current : "1" |
||||
/// orders : [{"column":"id","asc":false}] |
||||
/// hitCount : false |
||||
/// searchCount : true |
||||
/// pages : "1" |
||||
|
||||
class TitleInfoList { |
||||
TitleInfoList({ |
||||
List<Records>? records, |
||||
String? total, |
||||
String? size, |
||||
String? current, |
||||
List<Orders>? orders, |
||||
bool? hitCount, |
||||
bool? searchCount, |
||||
String? pages,}){ |
||||
_records = records; |
||||
_total = total; |
||||
_size = size; |
||||
_current = current; |
||||
_orders = orders; |
||||
_hitCount = hitCount; |
||||
_searchCount = searchCount; |
||||
_pages = pages; |
||||
} |
||||
|
||||
TitleInfoList.fromJson(dynamic json) { |
||||
if (json['records'] != null) { |
||||
_records = []; |
||||
json['records'].forEach((v) { |
||||
_records?.add(Records.fromJson(v)); |
||||
}); |
||||
} |
||||
_total = json['total']; |
||||
_size = json['size']; |
||||
_current = json['current']; |
||||
if (json['orders'] != null) { |
||||
_orders = []; |
||||
json['orders'].forEach((v) { |
||||
_orders?.add(Orders.fromJson(v)); |
||||
}); |
||||
} |
||||
_hitCount = json['hitCount']; |
||||
_searchCount = json['searchCount']; |
||||
_pages = json['pages']; |
||||
} |
||||
List<Records>? _records; |
||||
String? _total; |
||||
String? _size; |
||||
String? _current; |
||||
List<Orders>? _orders; |
||||
bool? _hitCount; |
||||
bool? _searchCount; |
||||
String? _pages; |
||||
TitleInfoList copyWith({ List<Records>? records, |
||||
String? total, |
||||
String? size, |
||||
String? current, |
||||
List<Orders>? orders, |
||||
bool? hitCount, |
||||
bool? searchCount, |
||||
String? pages, |
||||
}) => TitleInfoList( records: records ?? _records, |
||||
total: total ?? _total, |
||||
size: size ?? _size, |
||||
current: current ?? _current, |
||||
orders: orders ?? _orders, |
||||
hitCount: hitCount ?? _hitCount, |
||||
searchCount: searchCount ?? _searchCount, |
||||
pages: pages ?? _pages, |
||||
); |
||||
List<Records>? get records => _records; |
||||
String? get total => _total; |
||||
String? get size => _size; |
||||
String? get current => _current; |
||||
List<Orders>? get orders => _orders; |
||||
bool? get hitCount => _hitCount; |
||||
bool? get searchCount => _searchCount; |
||||
String? get pages => _pages; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
if (_records != null) { |
||||
map['records'] = _records?.map((v) => v.toJson()).toList(); |
||||
} |
||||
map['total'] = _total; |
||||
map['size'] = _size; |
||||
map['current'] = _current; |
||||
if (_orders != null) { |
||||
map['orders'] = _orders?.map((v) => v.toJson()).toList(); |
||||
} |
||||
map['hitCount'] = _hitCount; |
||||
map['searchCount'] = _searchCount; |
||||
map['pages'] = _pages; |
||||
return map; |
||||
} |
||||
|
||||
} |
||||
|
||||
/// column : "id" |
||||
/// asc : false |
||||
|
||||
class Orders { |
||||
Orders({ |
||||
String? column, |
||||
bool? asc,}){ |
||||
_column = column; |
||||
_asc = asc; |
||||
} |
||||
|
||||
Orders.fromJson(dynamic json) { |
||||
_column = json['column']; |
||||
_asc = json['asc']; |
||||
} |
||||
String? _column; |
||||
bool? _asc; |
||||
Orders copyWith({ String? column, |
||||
bool? asc, |
||||
}) => Orders( column: column ?? _column, |
||||
asc: asc ?? _asc, |
||||
); |
||||
String? get column => _column; |
||||
bool? get asc => _asc; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['column'] = _column; |
||||
map['asc'] = _asc; |
||||
return map; |
||||
} |
||||
|
||||
} |
||||
|
||||
/// id : "1820725763083599872" |
||||
/// createTime : "2024-08-06 15:37:04" |
||||
/// createUser : "1379254113602109440" |
||||
/// updateTime : "2024-08-06 15:37:04" |
||||
/// updateUser : "1379254113602109440" |
||||
/// userId : "1379254113602109440" |
||||
/// isDefault : 1 |
||||
/// type : "PERSONAL" |
||||
/// name : "哈哈" |
||||
/// taxId : "" |
||||
/// companyAddr : "" |
||||
/// companyPhone : "" |
||||
/// bank : "" |
||||
/// bankNumber : "" |
||||
/// isDelete : 0 |
||||
|
||||
class Records { |
||||
Records({ |
||||
String? id, |
||||
String? createTime, |
||||
String? createUser, |
||||
String? updateTime, |
||||
String? updateUser, |
||||
String? userId, |
||||
num? isDefault, |
||||
String? type, |
||||
String? name, |
||||
String? taxId, |
||||
String? companyAddr, |
||||
String? companyPhone, |
||||
String? bank, |
||||
String? bankNumber, |
||||
num? isDelete,}){ |
||||
_id = id; |
||||
_createTime = createTime; |
||||
_createUser = createUser; |
||||
_updateTime = updateTime; |
||||
_updateUser = updateUser; |
||||
_userId = userId; |
||||
_isDefault = isDefault; |
||||
_type = type; |
||||
_name = name; |
||||
_taxId = taxId; |
||||
_companyAddr = companyAddr; |
||||
_companyPhone = companyPhone; |
||||
_bank = bank; |
||||
_bankNumber = bankNumber; |
||||
_isDelete = isDelete; |
||||
} |
||||
|
||||
Records.fromJson(dynamic json) { |
||||
_id = json['id']; |
||||
_createTime = json['createTime']; |
||||
_createUser = json['createUser']; |
||||
_updateTime = json['updateTime']; |
||||
_updateUser = json['updateUser']; |
||||
_userId = json['userId']; |
||||
_isDefault = json['isDefault']; |
||||
_type = json['type']; |
||||
_name = json['name']; |
||||
_taxId = json['taxId']; |
||||
_companyAddr = json['companyAddr']; |
||||
_companyPhone = json['companyPhone']; |
||||
_bank = json['bank']; |
||||
_bankNumber = json['bankNumber']; |
||||
_isDelete = json['isDelete']; |
||||
} |
||||
String? _id; |
||||
String? _createTime; |
||||
String? _createUser; |
||||
String? _updateTime; |
||||
String? _updateUser; |
||||
String? _userId; |
||||
num? _isDefault; |
||||
String? _type; |
||||
String? _name; |
||||
String? _taxId; |
||||
String? _companyAddr; |
||||
String? _companyPhone; |
||||
String? _bank; |
||||
String? _bankNumber; |
||||
num? _isDelete; |
||||
Records copyWith({ String? id, |
||||
String? createTime, |
||||
String? createUser, |
||||
String? updateTime, |
||||
String? updateUser, |
||||
String? userId, |
||||
num? isDefault, |
||||
String? type, |
||||
String? name, |
||||
String? taxId, |
||||
String? companyAddr, |
||||
String? companyPhone, |
||||
String? bank, |
||||
String? bankNumber, |
||||
num? isDelete, |
||||
}) => Records( id: id ?? _id, |
||||
createTime: createTime ?? _createTime, |
||||
createUser: createUser ?? _createUser, |
||||
updateTime: updateTime ?? _updateTime, |
||||
updateUser: updateUser ?? _updateUser, |
||||
userId: userId ?? _userId, |
||||
isDefault: isDefault ?? _isDefault, |
||||
type: type ?? _type, |
||||
name: name ?? _name, |
||||
taxId: taxId ?? _taxId, |
||||
companyAddr: companyAddr ?? _companyAddr, |
||||
companyPhone: companyPhone ?? _companyPhone, |
||||
bank: bank ?? _bank, |
||||
bankNumber: bankNumber ?? _bankNumber, |
||||
isDelete: isDelete ?? _isDelete, |
||||
); |
||||
String? get id => _id; |
||||
String? get createTime => _createTime; |
||||
String? get createUser => _createUser; |
||||
String? get updateTime => _updateTime; |
||||
String? get updateUser => _updateUser; |
||||
String? get userId => _userId; |
||||
num? get isDefault => _isDefault; |
||||
String? get type => _type; |
||||
String? get name => _name; |
||||
String? get taxId => _taxId; |
||||
String? get companyAddr => _companyAddr; |
||||
String? get companyPhone => _companyPhone; |
||||
String? get bank => _bank; |
||||
String? get bankNumber => _bankNumber; |
||||
num? get isDelete => _isDelete; |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
final map = <String, dynamic>{}; |
||||
map['id'] = _id; |
||||
map['createTime'] = _createTime; |
||||
map['createUser'] = _createUser; |
||||
map['updateTime'] = _updateTime; |
||||
map['updateUser'] = _updateUser; |
||||
map['userId'] = _userId; |
||||
map['isDefault'] = _isDefault; |
||||
map['type'] = _type; |
||||
map['name'] = _name; |
||||
map['taxId'] = _taxId; |
||||
map['companyAddr'] = _companyAddr; |
||||
map['companyPhone'] = _companyPhone; |
||||
map['bank'] = _bank; |
||||
map['bankNumber'] = _bankNumber; |
||||
map['isDelete'] = _isDelete; |
||||
return map; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,599 @@
|
||||
import 'dart:convert'; |
||||
|
||||
import 'package:dio/dio.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter/services.dart'; |
||||
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:shared_preferences/shared_preferences.dart'; |
||||
import 'package:shimmer/shimmer.dart'; |
||||
|
||||
import '../../data/base_data.dart'; |
||||
import '../../generated/l10n.dart'; |
||||
import '../../retrofit/retrofit_api.dart'; |
||||
import '../../utils/flutter_utils.dart'; |
||||
import '../../utils/font_weight.dart'; |
||||
import '../../view_widget/my_appbar.dart'; |
||||
|
||||
class EditInvoicesInfo extends StatefulWidget { |
||||
final Map<String, dynamic>? arguments; |
||||
|
||||
EditInvoicesInfo({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _EditInvoicesInfo(); |
||||
} |
||||
} |
||||
|
||||
class _EditInvoicesInfo extends State<EditInvoicesInfo> { |
||||
bool isKeyBoardShow = false; |
||||
FocusNode _focusNode = FocusNode(); |
||||
String? selectPrice; |
||||
String headerId = ""; |
||||
String phone = ""; |
||||
String name = ""; |
||||
ApiService? apiService; |
||||
Map? invoicesInfo; |
||||
String? mobile; |
||||
final TextEditingController editPhoneController = TextEditingController(); |
||||
List<dynamic>? ids; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
WidgetsBinding.instance.addPostFrameCallback((_) { |
||||
setState(() { |
||||
print("object: ${MediaQuery.of(context).viewInsets.bottom}"); |
||||
if (MediaQuery.of(context).viewInsets.bottom == 0) { |
||||
if (isKeyBoardShow) { |
||||
isKeyBoardShow = false; |
||||
//关闭键盘 软键盘关闭了, 清除输入控件的焦点, 否则重新进入页面会导致软键盘再弹出问题 |
||||
FocusScope.of(context).requestFocus(FocusNode()); |
||||
} |
||||
} else { |
||||
isKeyBoardShow = true; |
||||
} |
||||
}); |
||||
}); |
||||
SharedPreferences.getInstance().then((value) => { |
||||
apiService = ApiService(Dio(), |
||||
context: context, token: value.getString('token'),), |
||||
setState(() { |
||||
mobile = value.getString('mobile'); |
||||
}) |
||||
}); |
||||
selectPrice = widget.arguments?["selectPrice"] ?? ""; |
||||
ids = widget.arguments?["ids"] ?? []; |
||||
} |
||||
|
||||
///离开页面记着销毁和清除 |
||||
@override |
||||
void dispose() { |
||||
super.dispose(); |
||||
_focusNode.unfocus(); |
||||
} |
||||
|
||||
///提交发票审核 |
||||
submitInvoiceReview() async { |
||||
try { |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, |
||||
maskType: EasyLoadingMaskType.black); |
||||
BaseData? baseData = await apiService?.invoiceSubmit({ |
||||
"headerId": headerId, //选择的抬头id |
||||
"isDelete": 0, |
||||
"money": selectPrice, //开票金额 |
||||
"orderIds": ids, //开票的订单id数组 |
||||
"ossId": 0, |
||||
"phone": phone, //抬头保存的号码 |
||||
"reason": "", |
||||
"reviewerBy": 0, |
||||
"reviewerTime": "", |
||||
"state": 0, |
||||
"type": 1, |
||||
"receivingPhone": editPhoneController.text == "" ? mobile :editPhoneController.text, //申请人手机号码 |
||||
}).catchError((error) { |
||||
SmartDialog.showToast(AppUtils.dioErrorTypeToString(error.type), |
||||
alignment: Alignment.center); |
||||
}); |
||||
if (baseData?.isSuccess ?? false) { |
||||
Navigator.of(context).pop(1); |
||||
} else { |
||||
SmartDialog.showToast("${baseData?.msg}", alignment: Alignment.center); |
||||
} |
||||
} finally { |
||||
EasyLoading.dismiss(); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.translucent, |
||||
onTap: () { |
||||
FocusScope.of(context).unfocus(); |
||||
}, |
||||
child: Scaffold( |
||||
resizeToAvoidBottomInset: false, |
||||
appBar: MyAppBar( |
||||
title: "填写发票信息", |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
), |
||||
body: // networkStatus == -1 ? noNetwork() : |
||||
Container( |
||||
margin: EdgeInsets.only(top: 12.h), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Expanded( |
||||
child: SingleChildScrollView( |
||||
physics: BouncingScrollPhysics(), |
||||
child: Container( |
||||
padding: EdgeInsets.symmetric(horizontal: 17.w), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
///业务流程需求暂时用不到 |
||||
// Container( |
||||
// padding: EdgeInsets.only( |
||||
// top: 12.h, bottom: 12.h, left: 12.w, right: 10.w), |
||||
// margin: EdgeInsets.only(bottom: 12.h), |
||||
// decoration: BoxDecoration( |
||||
// color: Colors.white, |
||||
// borderRadius: BorderRadius.circular(6), |
||||
// boxShadow: [ |
||||
// BoxShadow( |
||||
// color: Color(0x0F06152E), |
||||
// offset: Offset(0, 2), |
||||
// blurRadius: 4, |
||||
// spreadRadius: 0, |
||||
// ) |
||||
// ], |
||||
// ), |
||||
// child: Row( |
||||
// crossAxisAlignment: CrossAxisAlignment.start, |
||||
// children: [ |
||||
// Padding( |
||||
// padding: EdgeInsets.only(top: 5.h), |
||||
// child: Image.asset( |
||||
// "assets/image/tip_info.webp", |
||||
// width: 17.h, |
||||
// height: 17.h, |
||||
// fit: BoxFit.fill, |
||||
// ), |
||||
// ), |
||||
// Padding( |
||||
// padding: EdgeInsets.only(left: 5.w), |
||||
// child: Text( |
||||
// "失败原因:已经开具过纸质发票,不能重复开具\n电子发票", |
||||
// style: TextStyle( |
||||
// letterSpacing: 0.5, |
||||
// height: 1.5, |
||||
// color: Color(0xFF32A060), |
||||
// fontSize: 14.sp, |
||||
// fontWeight: MyFontWeight.regular, |
||||
// ), |
||||
// ), |
||||
// ) |
||||
// ], |
||||
// ), |
||||
// ), |
||||
Container( |
||||
padding: |
||||
EdgeInsets.only(top: 16.h, bottom: 16.h, left: 18.w), |
||||
margin: EdgeInsets.symmetric(vertical: 12.h), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(6), |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Color(0x0F06152E), |
||||
offset: Offset(0, 2), |
||||
blurRadius: 4, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Text( |
||||
"发票抬头", |
||||
style: TextStyle( |
||||
color: Color(0xFF1A1A1A), |
||||
fontSize: 15.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(top: 16.h, bottom: 18.h), |
||||
child: Row( |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(right: 31.w), |
||||
child: Text( |
||||
"发票类型", |
||||
style: TextStyle( |
||||
color: Color(0xFF1A1A1A), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
)), |
||||
Text( |
||||
"电子发票", |
||||
style: TextStyle( |
||||
color: Color(0xFF32A060), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.translucent, |
||||
onTap: () { |
||||
Navigator.of(context) |
||||
.pushNamed('/router/invoices_title_info',arguments:{ |
||||
"enterType":0, |
||||
}) |
||||
.then((value) { |
||||
if(value != null){ |
||||
invoicesInfo = value as Map?; |
||||
headerId = (value as Map)['id']; |
||||
phone = (value as Map)['phone']; |
||||
name = (value as Map)['name']; |
||||
setState(() {}); |
||||
} |
||||
}); |
||||
}, |
||||
child: Row( |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(right: 31.w), |
||||
child: Text( |
||||
"发票抬头", |
||||
style: TextStyle( |
||||
color: Color(0xFF1A1A1A), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
)), |
||||
Expanded( |
||||
child: Text( |
||||
name == "" ? "请选择" : name, |
||||
style: TextStyle( |
||||
color: Color(0xFF1A1A1A), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
)), |
||||
Padding( |
||||
padding: EdgeInsets.only(right: 21.w), |
||||
child: Icon(Icons.arrow_forward_ios, |
||||
color: Color(0xFF181818), |
||||
size: 14.sp)) |
||||
], |
||||
)) |
||||
], |
||||
), |
||||
), |
||||
Container( |
||||
padding: EdgeInsets.symmetric( |
||||
vertical: 16.h, horizontal: 17.w), |
||||
margin: EdgeInsets.symmetric(vertical: 12.h), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(6), |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Color(0x0F06152E), |
||||
offset: Offset(0, 2), |
||||
blurRadius: 4, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
), |
||||
child: Row( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"开票金额", |
||||
style: TextStyle( |
||||
color: Color(0xFF1A1A1A), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
)), |
||||
Padding( |
||||
padding: EdgeInsets.only(right: 6.w), |
||||
child: Text( |
||||
"可开票金额", |
||||
style: TextStyle( |
||||
color: Color(0xFF1A1A1A), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
), |
||||
Text( |
||||
"${selectPrice ?? "0"}元", |
||||
style: TextStyle( |
||||
color: Color(0xFF32A060), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
) |
||||
], |
||||
), |
||||
), |
||||
Container( |
||||
padding: EdgeInsets.symmetric(horizontal: 17.w), |
||||
margin: EdgeInsets.symmetric(vertical: 12.h), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(6), |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Color(0x0F06152E), |
||||
offset: Offset(0, 2), |
||||
blurRadius: 4, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
), |
||||
child: Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
"发票接收", |
||||
style: TextStyle( |
||||
color: Color(0xFF1A1A1A), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
Expanded( |
||||
child: TextField( |
||||
controller: editPhoneController, |
||||
decoration: InputDecoration( |
||||
hintText: mobile, |
||||
hintStyle: TextStyle( |
||||
color: Colors.black, |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
hintTextDirection: TextDirection.rtl, |
||||
border: InputBorder.none, |
||||
contentPadding: |
||||
EdgeInsets.only(left: 16.w), |
||||
), |
||||
textAlign: TextAlign.right, |
||||
style: TextStyle( |
||||
color: Colors.black, |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
)), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap:(){ |
||||
if(name == ""){ |
||||
SmartDialog.showToast("请选择发票抬头", |
||||
alignment: Alignment.center); |
||||
}else{ |
||||
submitInvoiceReview(); |
||||
} |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.symmetric(vertical:16.h), |
||||
margin: EdgeInsets.only(bottom:25.h,left:20.w,right: 20.w), |
||||
decoration: BoxDecoration( |
||||
color: Color(0xff32A060), |
||||
borderRadius: BorderRadius.circular( |
||||
45 |
||||
), |
||||
), |
||||
width: double.infinity, |
||||
alignment: Alignment.center, |
||||
child: Text( |
||||
"确认提交", |
||||
style: TextStyle( |
||||
color: Colors.white, |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
)); |
||||
} |
||||
|
||||
Widget editInvoicesInfoSm() { |
||||
return Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Container( |
||||
padding: EdgeInsets.only(top: 16.h, bottom: 16.h, left: 18.w), |
||||
margin: EdgeInsets.symmetric(vertical: 12.h), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(6), |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Color(0x0F06152E), |
||||
offset: Offset(0, 2), |
||||
blurRadius: 4, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 62, |
||||
height: 20, |
||||
), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(top: 16.h, bottom: 18.h), |
||||
child: Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 31.w), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 58, |
||||
height: 20, |
||||
), |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 58, |
||||
height: 20, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 31.w), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 58, |
||||
height: 20, |
||||
), |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 140, |
||||
height: 20, |
||||
), |
||||
), |
||||
Spacer(), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 21.w), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 14, |
||||
height: 14), |
||||
), |
||||
], |
||||
) |
||||
], |
||||
), |
||||
), |
||||
Container( |
||||
padding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 17.w), |
||||
margin: EdgeInsets.symmetric(vertical: 12.h), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(6), |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Color(0x0F06152E), |
||||
offset: Offset(0, 2), |
||||
blurRadius: 4, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
), |
||||
child: Row( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 58, |
||||
height: 20, |
||||
), |
||||
), |
||||
Spacer(), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 6.w), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 70, |
||||
height: 20, |
||||
), |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 31, |
||||
height: 20, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
], |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,820 @@
|
||||
import 'dart:async'; |
||||
import 'dart:io'; |
||||
|
||||
import 'package:dio/dio.dart'; |
||||
import 'package:flutter/foundation.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter/rendering.dart'; |
||||
import 'package:flutter/services.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:huixiang/order/invoices_manage/pdf_screen.dart'; |
||||
import 'package:path_provider/path_provider.dart'; |
||||
import 'package:pull_to_refresh/pull_to_refresh.dart'; |
||||
import 'package:shared_preferences/shared_preferences.dart'; |
||||
import 'package:shimmer/shimmer.dart'; |
||||
import 'package:url_launcher/url_launcher.dart'; |
||||
|
||||
import '../../community/photo_view_gallery_screen.dart'; |
||||
import '../../data/base_data.dart'; |
||||
import '../../data/invoices_detail_info.dart'; |
||||
import '../../retrofit/retrofit_api.dart'; |
||||
import '../../utils/flutter_utils.dart'; |
||||
import '../../utils/font_weight.dart'; |
||||
import '../../view_widget/classic_header.dart'; |
||||
import '../../view_widget/my_appbar.dart'; |
||||
import '../../view_widget/my_footer.dart'; |
||||
|
||||
class InvoicesDetailPage extends StatefulWidget { |
||||
final Map<String, dynamic>? arguments; |
||||
|
||||
InvoicesDetailPage({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _InvoicesDetailPage(); |
||||
} |
||||
} |
||||
|
||||
class _InvoicesDetailPage extends State<InvoicesDetailPage> { |
||||
ApiService? apiService; |
||||
InvoicesDetailInfo? invoicesDetailInfo; |
||||
String remotePDFpath = ""; |
||||
String networkError = ""; |
||||
int networkStatus = 0; |
||||
final RefreshController refreshController = RefreshController(); |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
SharedPreferences.getInstance().then((value) => { |
||||
apiService = ApiService( |
||||
Dio(), |
||||
context: context, |
||||
token: value.getString('token'), |
||||
), |
||||
queryInvoices("1797587255380934656"), |
||||
}); |
||||
} |
||||
|
||||
///离开页面记着销毁和清除 |
||||
@override |
||||
void dispose() { |
||||
super.dispose(); |
||||
refreshController.dispose(); |
||||
} |
||||
|
||||
///发票详情 |
||||
queryInvoices(id) async { |
||||
if (apiService == null) { |
||||
SharedPreferences value = await SharedPreferences.getInstance(); |
||||
apiService = ApiService( |
||||
Dio(), |
||||
context: context, |
||||
token: value.getString("token"), |
||||
); |
||||
} |
||||
BaseData<InvoicesDetailInfo>? baseData = |
||||
await apiService?.invoiceDetail(id).catchError((error) { |
||||
networkError = AppUtils.dioErrorTypeToString(error.type); |
||||
networkStatus = -1; |
||||
setState(() {}); |
||||
refreshController.refreshFailed(); |
||||
refreshController.loadFailed(); |
||||
}); |
||||
if (baseData?.isSuccess ?? false) { |
||||
invoicesDetailInfo = baseData?.data; |
||||
createFileOfPdfUrl().then((f) { |
||||
setState(() { |
||||
remotePDFpath = f.path; |
||||
}); |
||||
}); |
||||
refreshController.refreshCompleted(); |
||||
networkStatus = 1; |
||||
setState(() {}); |
||||
} else { |
||||
refreshController.refreshFailed(); |
||||
refreshController.loadFailed(); |
||||
SmartDialog.showToast("${baseData?.msg}", alignment: Alignment.center); |
||||
} |
||||
} |
||||
|
||||
///从网络下载 PDF 文件。 |
||||
Future<File> createFileOfPdfUrl() async { |
||||
Completer<File> completer = Completer(); |
||||
print("Start download file from internet!"); |
||||
try { |
||||
final url = invoicesDetailInfo?.ossUrl ?? ""; |
||||
final filename = url.substring(url.lastIndexOf("/") + 1); |
||||
var request = await HttpClient().getUrl(Uri.parse(url)); |
||||
var response = await request.close(); |
||||
var bytes = await consolidateHttpClientResponseBytes(response); |
||||
var dir = await getApplicationDocumentsDirectory(); |
||||
print("Download files"); |
||||
print("${dir.path}/$filename"); |
||||
File file = File("${dir.path}/$filename"); |
||||
|
||||
await file.writeAsBytes(bytes, flush: true); |
||||
completer.complete(file); |
||||
} catch (e) { |
||||
throw Exception('Error parsing asset file!'); |
||||
} |
||||
return completer.future; |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
resizeToAvoidBottomInset: false, |
||||
appBar: MyAppBar( |
||||
title: "发票详情", |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
), |
||||
body: networkStatus == -1 |
||||
? noNetwork() |
||||
: (networkStatus == 0 |
||||
? invoicesSm() |
||||
: SmartRefresher( |
||||
controller: refreshController, |
||||
enablePullDown: true, |
||||
header: MyHeader(), |
||||
footer: CustomFooter( |
||||
builder: (context, mode) { |
||||
return MyFooter(mode); |
||||
}, |
||||
), |
||||
onRefresh: () { |
||||
queryInvoices(widget.arguments?["id"] ?? ""); |
||||
}, |
||||
physics: BouncingScrollPhysics(), |
||||
scrollController: ScrollController(), |
||||
child: Container( |
||||
margin: EdgeInsets.only(top: 12.h), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Expanded( |
||||
child: Container( |
||||
padding: EdgeInsets.symmetric(horizontal: 17.w), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Container( |
||||
padding: EdgeInsets.symmetric( |
||||
vertical: 16.h, horizontal: 18.w), |
||||
margin: EdgeInsets.symmetric(vertical: 12.h), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(6), |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Color(0x0F06152E), |
||||
offset: Offset(0, 2), |
||||
blurRadius: 4, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Text( |
||||
"电子发票资讯", |
||||
style: TextStyle( |
||||
color: Color(0xFF1A1A1A), |
||||
fontSize: 15.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only( |
||||
top: 16.h, bottom: 18.h), |
||||
child: Row( |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"发票状态", |
||||
style: TextStyle( |
||||
color: Color(0xFF1A1A1A), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
)), |
||||
Text( |
||||
invoicesState( |
||||
invoicesDetailInfo?.state ?? |
||||
""), |
||||
style: TextStyle( |
||||
color: Color(0xFF32A060), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 18.h), |
||||
child: Row( |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"发票抬头", |
||||
style: TextStyle( |
||||
color: Color(0xFF1A1A1A), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
)), |
||||
Expanded( |
||||
child: Text( |
||||
invoicesDetailInfo |
||||
?.invoiceHeaderName ?? |
||||
"", |
||||
maxLines: 1, |
||||
overflow: TextOverflow.ellipsis, |
||||
textAlign: TextAlign.end, |
||||
style: TextStyle( |
||||
color: Color(0xFF1A1A1A), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
)), |
||||
], |
||||
), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 18.h), |
||||
child: Row( |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"申请时间", |
||||
style: TextStyle( |
||||
color: Color(0xFF1A1A1A), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
)), |
||||
Text( |
||||
invoicesDetailInfo?.reviewerTime ?? |
||||
"", |
||||
style: TextStyle( |
||||
color: Color(0xFF1A1A1A), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
Row( |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"开票金额", |
||||
style: TextStyle( |
||||
color: Color(0xFF1A1A1A), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
)), |
||||
Text( |
||||
invoicesDetailInfo?.money ?? "", |
||||
style: TextStyle( |
||||
color: Color(0xFF1A1A1A), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
], |
||||
) |
||||
], |
||||
), |
||||
), |
||||
GestureDetector( |
||||
onTap: () { |
||||
if ((invoicesDetailInfo?.ossUrl ?? "") |
||||
.endsWith("pdf")) { |
||||
Navigator.push( |
||||
context, |
||||
MaterialPageRoute( |
||||
builder: (context) => PDFScreen( |
||||
path: remotePDFpath, |
||||
inlet: 0, |
||||
), |
||||
), |
||||
); |
||||
} else { |
||||
Navigator.push( |
||||
context, |
||||
MaterialPageRoute( |
||||
builder: (context) => |
||||
PhotoViewGalleryScreen( |
||||
images: [ |
||||
invoicesDetailInfo?.ossUrl ?? "" |
||||
], //传入图片list |
||||
index: 0, //传入当前点击的图片的index |
||||
), |
||||
)); |
||||
} |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.symmetric( |
||||
vertical: 16.h, horizontal: 17.w), |
||||
margin: EdgeInsets.symmetric(vertical: 12.h), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(6), |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Color(0x0F06152E), |
||||
offset: Offset(0, 2), |
||||
blurRadius: 4, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
), |
||||
child: Row( |
||||
crossAxisAlignment: |
||||
CrossAxisAlignment.start, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
"1张发票,含${invoicesDetailInfo?.orderList?.length ?? 0}个订单", |
||||
style: TextStyle( |
||||
color: Color(0xFF1A1A1A), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
)), |
||||
Padding( |
||||
padding: EdgeInsets.only(right: 6.w), |
||||
child: Text( |
||||
"查看", |
||||
style: TextStyle( |
||||
color: Color(0xFF1A1A1A), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
), |
||||
Icon(Icons.arrow_forward_ios, |
||||
color: Color(0xFF181818), size: 14.sp) |
||||
], |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
)), |
||||
Row( |
||||
children: [ |
||||
Expanded( |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
if ((invoicesDetailInfo?.ossUrl ?? "") |
||||
.endsWith("pdf")) { |
||||
showPdfAlertDialog(); |
||||
} else { |
||||
Navigator.push( |
||||
context, |
||||
MaterialPageRoute( |
||||
builder: (context) => |
||||
PhotoViewGalleryScreen( |
||||
images: [ |
||||
invoicesDetailInfo?.ossUrl ?? "" |
||||
], //传入图片list |
||||
index: 0, //传入当前点击的图片的index |
||||
), |
||||
)); |
||||
} |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.symmetric(vertical: 16.h), |
||||
margin: EdgeInsets.only( |
||||
bottom: 34.h, right: 9.5.w, left: 14.w), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(45), |
||||
border: Border.all( |
||||
color: Color(0xff32A060), |
||||
width: 1.w, |
||||
), |
||||
), |
||||
width: double.infinity, |
||||
alignment: Alignment.center, |
||||
child: Text( |
||||
"查看电子发票", |
||||
style: TextStyle( |
||||
color: Color(0xff32A060), |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
), |
||||
), |
||||
), |
||||
)), |
||||
Expanded( |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
launchBrowser(); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.symmetric(vertical: 16.h), |
||||
margin: EdgeInsets.only( |
||||
bottom: 34.h, left: 9.5.w, right: 14.w), |
||||
decoration: BoxDecoration( |
||||
color: Color(0xff32A060), |
||||
borderRadius: BorderRadius.circular(45), |
||||
), |
||||
width: double.infinity, |
||||
alignment: Alignment.center, |
||||
child: Text( |
||||
"下载电子发票", |
||||
style: TextStyle( |
||||
color: Colors.white, |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
), |
||||
), |
||||
), |
||||
)), |
||||
], |
||||
) |
||||
], |
||||
), |
||||
), |
||||
)), |
||||
); |
||||
} |
||||
|
||||
///发票状态 |
||||
String invoicesState(state) { |
||||
if (state == "UN_AUDIT") { |
||||
return "待审核"; |
||||
} else if (state == "AUDIT_PASS") { |
||||
return "开票成功"; |
||||
} else if (state == "AUDIT_VOID") { |
||||
return "已作废"; |
||||
} else if (state == "AUDIT_FAIL") { |
||||
return "开票失败"; |
||||
} else { |
||||
return ""; |
||||
} |
||||
} |
||||
|
||||
///查看电子发票 |
||||
showPdfAlertDialog() { |
||||
//显示对话框 |
||||
showDialog( |
||||
context: context, |
||||
builder: (BuildContext context) { |
||||
return PDFScreen(path: remotePDFpath, inlet: 1); |
||||
}, |
||||
); |
||||
} |
||||
|
||||
///下载电子发票 |
||||
launchBrowser() async { |
||||
String url = invoicesDetailInfo?.ossUrl ?? ""; |
||||
if (await canLaunch(url)) { |
||||
await launch(url); |
||||
} else { |
||||
throw 'Could not launch $url'; |
||||
} |
||||
} |
||||
|
||||
Widget invoicesSm() { |
||||
return Container( |
||||
margin: EdgeInsets.only(top: 12.h), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Expanded( |
||||
child: Container( |
||||
padding: EdgeInsets.symmetric(horizontal: 17.w), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Container( |
||||
padding: |
||||
EdgeInsets.symmetric(vertical: 16.h, horizontal: 18.w), |
||||
margin: EdgeInsets.symmetric(vertical: 12.h), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(6), |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Color(0x0F06152E), |
||||
offset: Offset(0, 2), |
||||
blurRadius: 4, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
), |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 10), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 90.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(top: 16.h, bottom: 18.h), |
||||
child: Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 10), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 58.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
Spacer(), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 10), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 58.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 18.h), |
||||
child: Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 10), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 58.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
Spacer(), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 10), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 58.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 18.h), |
||||
child: Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 10), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 58.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
Spacer(), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 10), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 58.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 10), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 58.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
Spacer(), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 10), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 58.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
], |
||||
) |
||||
], |
||||
), |
||||
), |
||||
Container( |
||||
padding: |
||||
EdgeInsets.symmetric(vertical: 16.h, horizontal: 17.w), |
||||
margin: EdgeInsets.symmetric(vertical: 12.h), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
borderRadius: BorderRadius.circular(6), |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Color(0x0F06152E), |
||||
offset: Offset(0, 2), |
||||
blurRadius: 4, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
), |
||||
child: Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 10), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 124.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
Spacer(), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 10), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 28.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 18.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
], |
||||
), |
||||
)), |
||||
Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
// padding: EdgeInsets.symmetric(vertical: 16.h), |
||||
margin: |
||||
EdgeInsets.only(bottom: 34.h, right: 9.5.w, left: 14.w), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(45), |
||||
), |
||||
width: 164.w, |
||||
height: 48.h, |
||||
), |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
// padding: EdgeInsets.symmetric(vertical: 16.h), |
||||
margin: |
||||
EdgeInsets.only(bottom: 34.h, right: 9.5.w, left: 14.w), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(45), |
||||
), |
||||
width: 164.w, |
||||
height: 48.h, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget noNetwork() { |
||||
return Container( |
||||
width: double.infinity, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
// "无法连接到网络", |
||||
networkError.substring(0, networkError.indexOf(",")), |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xFF0D0D0D), |
||||
fontWeight: MyFontWeight.bold), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(vertical: 10.h), |
||||
child: Text( |
||||
"请检查网络设置或稍后重试", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
color: Color(0xFF7A797F), |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
queryInvoices(widget.arguments?["id"] ?? ""); |
||||
}, |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0xff32A060), |
||||
borderRadius: BorderRadius.circular(15), |
||||
), |
||||
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 3.h), |
||||
child: Text( |
||||
"重试", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Colors.white, |
||||
fontWeight: MyFontWeight.regular), |
||||
)), |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,462 @@
|
||||
import 'package:dio/dio.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter/services.dart'; |
||||
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:huixiang/data/invoices_history_list.dart'; |
||||
import 'package:pull_to_refresh/pull_to_refresh.dart'; |
||||
import 'package:shared_preferences/shared_preferences.dart'; |
||||
import 'package:shimmer/shimmer.dart'; |
||||
|
||||
import '../../data/base_data.dart'; |
||||
import '../../generated/l10n.dart'; |
||||
import '../../retrofit/retrofit_api.dart'; |
||||
import '../../utils/flutter_utils.dart'; |
||||
import '../../utils/font_weight.dart'; |
||||
import '../../view_widget/classic_header.dart'; |
||||
import '../../view_widget/my_appbar.dart'; |
||||
import '../../view_widget/my_footer.dart'; |
||||
import '../../view_widget/no_data_view.dart'; |
||||
|
||||
class InvoicesHistory extends StatefulWidget { |
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _InvoicesHistory(); |
||||
} |
||||
} |
||||
|
||||
class _InvoicesHistory extends State<InvoicesHistory> { |
||||
final RefreshController refreshController = RefreshController(); |
||||
ApiService? apiService; |
||||
String networkError = ""; |
||||
int networkStatus = 0; |
||||
List<Records> records = []; |
||||
int _current = 1; |
||||
Map<String,List<Records>> _map = {}; |
||||
String? _timeList; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
_onRefresh(); |
||||
} |
||||
|
||||
///离开页面记着销毁和清除 |
||||
@override |
||||
void dispose() { |
||||
super.dispose(); |
||||
refreshController.dispose(); |
||||
} |
||||
|
||||
///开票列表 |
||||
queryInvoiceList() async { |
||||
if (apiService == null) { |
||||
SharedPreferences value = await SharedPreferences.getInstance(); |
||||
apiService = ApiService(Dio(), |
||||
context: context, |
||||
token: value.getString("token"), |
||||
showLoading: false); |
||||
} |
||||
BaseData<InvoicesHistoryList>? baseData = await apiService?.invoicePage({ |
||||
"current": _current, |
||||
"size": 10, |
||||
"searchKey": "", |
||||
}).catchError((error) { |
||||
networkError = AppUtils.dioErrorTypeToString(error.type); |
||||
networkStatus = -1; |
||||
setState(() {}); |
||||
refreshController.refreshFailed(); |
||||
refreshController.loadFailed(); |
||||
}); |
||||
if (!mounted) return; |
||||
if (baseData?.isSuccess ?? false) { |
||||
records.addAll(baseData?.data?.records ?? []); |
||||
(baseData?.data?.records ?? []).forEach((element) { |
||||
if(_map.containsKey((element.reviewerTime ?? element.createTime).toString().substring(0,7))){ |
||||
_map[(element.reviewerTime ?? element.createTime).toString().substring(0,7)]?.add(element); |
||||
}else{ |
||||
_map[(element.reviewerTime ?? element.createTime).toString().substring(0,7)] = [element]; |
||||
} |
||||
}); |
||||
if(_map.isNotEmpty) |
||||
_timeList = _map.keys.toList().first; |
||||
if ((baseData?.data?.records ?? []).isEmpty || |
||||
records.length.toString() == baseData?.data?.total) |
||||
refreshController.loadNoData(); |
||||
else |
||||
refreshController.loadComplete(); |
||||
networkStatus = 1; |
||||
} else { |
||||
SmartDialog.showToast("${baseData?.msg}", alignment: Alignment.center); |
||||
} |
||||
} |
||||
|
||||
_onRefresh({bool isShowLoad = true}) async { |
||||
if (isShowLoad) |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, |
||||
maskType: EasyLoadingMaskType.black); |
||||
await queryInvoiceList(); |
||||
EasyLoading.dismiss(); |
||||
if (!mounted) return; |
||||
if (refreshController.isRefresh) refreshController.refreshCompleted(); |
||||
setState(() {}); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
resizeToAvoidBottomInset: false, |
||||
appBar: MyAppBar( |
||||
title: "开票历史", |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
), |
||||
body: |
||||
networkStatus == -1 ? noNetwork() : |
||||
Container( |
||||
child: SmartRefresher( |
||||
controller: refreshController, |
||||
enablePullDown: true, |
||||
enablePullUp: records.length == 0 ? false : true, |
||||
header: MyHeader(), |
||||
footer: CustomFooter( |
||||
builder: (context, mode) { |
||||
return MyFooter(mode); |
||||
}, |
||||
), |
||||
onRefresh: () { |
||||
_current = 1; |
||||
records.clear(); |
||||
_onRefresh(isShowLoad: false); |
||||
}, |
||||
onLoading: () { |
||||
_current++; |
||||
_onRefresh(isShowLoad: false); |
||||
}, |
||||
physics: BouncingScrollPhysics(), |
||||
scrollController: ScrollController(), |
||||
child: Container( |
||||
child: networkStatus == 0 |
||||
? Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(bottom: 16.h,top: 16.h,left: 17.w), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 70.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
Expanded(child: ListView.builder( |
||||
itemCount: 10, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () {}, |
||||
child: invoicesHistoryListSm(), |
||||
); |
||||
}, |
||||
)), |
||||
], |
||||
) |
||||
: |
||||
((records == null || records.length == 0) |
||||
? NoDataView( |
||||
src: "assets/image/ding_dan.webp", |
||||
isShowBtn: false, |
||||
text: "暂无开票记录", |
||||
fontSize: 16, |
||||
margin: EdgeInsets.only(top: 120,left: 20,right: 20), |
||||
) |
||||
: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(top: 16.h, bottom: 16.h, left: 17.w), |
||||
child: Text( |
||||
_timeList.toString(), |
||||
style: TextStyle( |
||||
color: Color(0xff1A1A1A), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
)), |
||||
Expanded(child: ListView.builder( |
||||
itemCount: records?.length ?? 0, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
// if(records[position].state == "AUDIT_PASS") |
||||
Navigator.of(context) |
||||
.pushNamed('/router/invoices_detail_page',arguments: { |
||||
"id":records[position].id ?? "" |
||||
}); |
||||
}, |
||||
child: invoicesHistoryList(records[position]), |
||||
); |
||||
}, |
||||
)) |
||||
], |
||||
)),), |
||||
), |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget invoicesHistoryList(Records records) { |
||||
return Container( |
||||
padding: EdgeInsets.symmetric(vertical: 14.h, horizontal: 12.w), |
||||
margin: EdgeInsets.only(left: 12.w, right: 12.w, bottom: 12.h), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Color(0x0F06152E), |
||||
offset: Offset(0, 2), |
||||
blurRadius: 4, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
borderRadius: BorderRadius.circular(8), |
||||
), |
||||
child: Column( |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 25.h), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
records?.invoiceHeaderName ?? "", |
||||
style: TextStyle( |
||||
color: Colors.black, |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
)), |
||||
Text( |
||||
invoicesStatus(records?.state ?? ""), |
||||
style: TextStyle( |
||||
color: Color(0xff32A060), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
) |
||||
], |
||||
), |
||||
), |
||||
Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(right: 16.w), |
||||
child: Text( |
||||
"¥${records?.money ?? ""}", |
||||
style: TextStyle( |
||||
color: Color(0xff32A060), |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
), |
||||
)), |
||||
Expanded( |
||||
child: Text( |
||||
"电子普票", |
||||
style: TextStyle( |
||||
color: Color(0xff32A060), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
)), |
||||
Text( |
||||
records?.reviewerTime ?? records?.createTime ?? "", |
||||
style: TextStyle( |
||||
color: Color(0xff4D4D4D), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
) |
||||
], |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
///发票状态 |
||||
String invoicesStatus(state) { |
||||
if (state == "UN_AUDIT") { |
||||
return "待审核"; |
||||
} else if (state =="AUDIT_PASS") { |
||||
return "开票成功"; |
||||
} else if (state =="AUDIT_VOID") { |
||||
return "已作废"; |
||||
}else if (state =="AUDIT_FAIL") { |
||||
return "开票失败"; |
||||
}else { |
||||
return ""; |
||||
} |
||||
} |
||||
|
||||
Widget invoicesHistoryListSm() { |
||||
return Container( |
||||
padding: EdgeInsets.symmetric(vertical: 14.h, horizontal: 12.w), |
||||
margin: EdgeInsets.symmetric(horizontal: 14.w, vertical: 12.h), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Color(0x0F06152E), |
||||
offset: Offset(0, 2), |
||||
blurRadius: 4, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
borderRadius: BorderRadius.circular(8), |
||||
), |
||||
child: Column( |
||||
children: [ |
||||
Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 24), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 180.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
Spacer(), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 25), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 42.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
SizedBox( |
||||
height: 25.h, |
||||
), |
||||
Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 20), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 47.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 56.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
Spacer(), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 25), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 80.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget noNetwork() { |
||||
return Container( |
||||
width: double.infinity, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
// "无法连接到网络", |
||||
networkError.substring(0, networkError.indexOf(",")), |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xFF0D0D0D), |
||||
fontWeight: MyFontWeight.bold), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(vertical: 10.h), |
||||
child: Text( |
||||
"请检查网络设置或稍后重试", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
color: Color(0xFF7A797F), |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
_onRefresh(); |
||||
}, |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0xff32A060), |
||||
borderRadius: BorderRadius.circular(15), |
||||
), |
||||
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 3.h), |
||||
child: Text( |
||||
"重试", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Colors.white, |
||||
fontWeight: MyFontWeight.regular), |
||||
)), |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,678 @@
|
||||
import 'package:dio/dio.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter/services.dart'; |
||||
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:pull_to_refresh/pull_to_refresh.dart'; |
||||
import 'package:shared_preferences/shared_preferences.dart'; |
||||
import 'package:shimmer/shimmer.dart'; |
||||
|
||||
import '../../data/base_data.dart'; |
||||
import '../../data/invoice_list.dart'; |
||||
import '../../generated/l10n.dart'; |
||||
import '../../retrofit/retrofit_api.dart'; |
||||
import '../../utils/flutter_utils.dart'; |
||||
import '../../utils/font_weight.dart'; |
||||
import '../../view_widget/classic_header.dart'; |
||||
import '../../view_widget/my_appbar.dart'; |
||||
import '../../view_widget/my_footer.dart'; |
||||
import '../../view_widget/no_data_view.dart'; |
||||
import '../../view_widget/settlement_tips_dialog.dart'; |
||||
|
||||
class InvoicesManagePage extends StatefulWidget { |
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _InvoicesManagePage(); |
||||
} |
||||
} |
||||
|
||||
class _InvoicesManagePage extends State<InvoicesManagePage> { |
||||
final RefreshController refreshController = RefreshController(); |
||||
ApiService? apiService; |
||||
String networkError = ""; |
||||
int networkStatus = 0; |
||||
int _pageNum = 1; |
||||
var allCheckIndex = false; |
||||
List<Records> records = []; |
||||
List<Records> unRecords = []; |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
_onRefresh(); |
||||
} |
||||
|
||||
///离开页面记着销毁和清除 |
||||
@override |
||||
void dispose() { |
||||
super.dispose(); |
||||
refreshController.dispose(); |
||||
} |
||||
|
||||
///开票列表 |
||||
queryInvoiceList() async { |
||||
if (apiService == null) { |
||||
SharedPreferences value = await SharedPreferences.getInstance(); |
||||
apiService = ApiService(Dio(), |
||||
context: context, |
||||
token: value.getString("token"), |
||||
showLoading: false); |
||||
} |
||||
BaseData<InvoiceList>? baseData = await apiService?.invoiceOrderList({ |
||||
"current": _pageNum, |
||||
"size": 10, |
||||
"searchKey": "", |
||||
}).catchError((error) { |
||||
networkError = AppUtils.dioErrorTypeToString(error.type); |
||||
networkStatus = -1; |
||||
setState(() {}); |
||||
refreshController.refreshFailed(); |
||||
refreshController.loadFailed(); |
||||
}); |
||||
if (!mounted) return; |
||||
if (baseData?.isSuccess ?? false) { |
||||
records.addAll(baseData?.data?.records ?? []); |
||||
baseData?.data?.records?.forEach((element) { |
||||
if ((double.tryParse(element.payedPrice ?? "")??0) > 0) |
||||
unRecords.add(element); |
||||
}); |
||||
if ((baseData?.data?.records ?? []).isEmpty || |
||||
records.length.toString() == baseData?.data?.total) |
||||
refreshController.loadNoData(); |
||||
else |
||||
refreshController.loadComplete(); |
||||
networkStatus = 1; |
||||
} else { |
||||
SmartDialog.showToast("${baseData?.msg}", alignment: Alignment.center); |
||||
} |
||||
} |
||||
|
||||
_onRefresh({bool isShowLoad = true}) async { |
||||
if (isShowLoad) |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, |
||||
maskType: EasyLoadingMaskType.black); |
||||
await queryInvoiceList(); |
||||
EasyLoading.dismiss(); |
||||
if (!mounted) return; |
||||
if (refreshController.isRefresh) refreshController.refreshCompleted(); |
||||
setState(() {}); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
resizeToAvoidBottomInset: false, |
||||
appBar: MyAppBar( |
||||
title: "发票管理", |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
), |
||||
body: networkStatus == -1 |
||||
? noNetwork() |
||||
: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Container( |
||||
color: Colors.white, |
||||
padding: EdgeInsets.only(top: 15.h, bottom: 10.h), |
||||
margin: EdgeInsets.only(bottom: 12.h), |
||||
child: Row( |
||||
children: [ |
||||
Expanded( |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.translucent, |
||||
onTap: () { |
||||
Navigator.of(context) |
||||
.pushNamed('/router/invoices_title_info',arguments:{ |
||||
"enterType":1, |
||||
}); |
||||
}, |
||||
child: Column( |
||||
children: [ |
||||
Image.asset( |
||||
"assets/image/invoice_title.webp", |
||||
width: 26.h, |
||||
height: 26.h, |
||||
fit: BoxFit.fitWidth, |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(top: 7.6.h), |
||||
child: Text( |
||||
"抬头管理", |
||||
style: TextStyle( |
||||
color: Colors.black, |
||||
fontSize: 14.sp, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
), |
||||
) |
||||
], |
||||
), |
||||
)), |
||||
Expanded( |
||||
child: GestureDetector( |
||||
behavior: HitTestBehavior.translucent, |
||||
onTap: () { |
||||
Navigator.of(context) |
||||
.pushNamed('/router/invoices_history'); |
||||
}, |
||||
child: Column( |
||||
children: [ |
||||
Image.asset( |
||||
"assets/image/invoice_history.webp", |
||||
width: 26.h, |
||||
height: 26.h, |
||||
fit: BoxFit.fitWidth, |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(top: 7.6.h), |
||||
child: Text( |
||||
"开票历史", |
||||
style: TextStyle( |
||||
color: Colors.black, |
||||
fontSize: 14.sp, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
), |
||||
) |
||||
], |
||||
))), |
||||
], |
||||
), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(left: 14.w, bottom: 6.h), |
||||
child: Text( |
||||
"可开票订单", |
||||
style: TextStyle( |
||||
color: Colors.black, |
||||
fontSize: 14.sp, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
textAlign: TextAlign.left, |
||||
), |
||||
), |
||||
Expanded( |
||||
child: Container( |
||||
child: SmartRefresher( |
||||
controller: refreshController, |
||||
enablePullDown: true, |
||||
enablePullUp:records.length == 0 ? false :true, |
||||
header: MyHeader(), |
||||
footer: CustomFooter( |
||||
builder: (context, mode) { |
||||
return MyFooter(mode); |
||||
}, |
||||
), |
||||
onRefresh: () { |
||||
_pageNum = 1; |
||||
records.clear(); |
||||
unRecords.clear(); |
||||
_onRefresh(isShowLoad: false); |
||||
}, |
||||
onLoading: () { |
||||
_pageNum++; |
||||
_onRefresh(isShowLoad: false); |
||||
}, |
||||
physics: BouncingScrollPhysics(), |
||||
scrollController: ScrollController(), |
||||
child: Container( |
||||
child: networkStatus == 0 |
||||
? ListView.builder( |
||||
itemCount: 10, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () {}, |
||||
child: invoicesOrderItemSm(), |
||||
); |
||||
}, |
||||
) |
||||
: ((records == null || records.length == 0) |
||||
? NoDataView( |
||||
src: "assets/image/ding_dan.webp", |
||||
isShowBtn: false, |
||||
text: "暂无可开票的订单", |
||||
fontSize: 16, |
||||
margin: EdgeInsets.only(top: 120,left: 20,right: 20), |
||||
) |
||||
: ListView.builder( |
||||
itemCount: records?.length ?? 0, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
setState(() { |
||||
records[position].isSelect = |
||||
!records[position].isSelect; |
||||
}); |
||||
}, |
||||
child: |
||||
invoicesOrderItem(records[position]), |
||||
); |
||||
}, |
||||
)), |
||||
), |
||||
), |
||||
)), |
||||
if (records != null && records.length > 0) |
||||
Container( |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
), |
||||
width: double.infinity, |
||||
padding: EdgeInsets.only( |
||||
top: 16.h, bottom: 45.h, left: 14.w, right: 17.w), |
||||
child: Column( |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(bottom: 10.h), |
||||
child: Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Padding( |
||||
padding: EdgeInsets.only(right: 6.w), |
||||
child: Text( |
||||
"已选${selectNum()}个订单合计:", |
||||
style: TextStyle( |
||||
color: Color(0xFF000000), |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: Text( |
||||
"¥${selectPrice()}", |
||||
style: TextStyle( |
||||
color: Color(0xFF32A060), |
||||
fontSize: 20.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
), |
||||
)), |
||||
Text( |
||||
"开票金额以实际发票为准", |
||||
style: TextStyle( |
||||
color: Color(0xFF727272), |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
], |
||||
)), |
||||
Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
GestureDetector( |
||||
onTap: () { |
||||
records.forEach((element) { |
||||
element.isSelect = !allCheckIndex; |
||||
}); |
||||
allCheckIndex = !allCheckIndex; |
||||
setState(() {}); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.only(right: 8.w), |
||||
child: Image.asset( |
||||
allCheckIndex |
||||
? "assets/image/icon_radio_selected.webp" |
||||
: "assets/image/icon_radio_unselected.webp", |
||||
width: 16.w, |
||||
height: 16.h, |
||||
)), |
||||
), |
||||
Expanded( |
||||
child: GestureDetector( |
||||
onTap: () { |
||||
records.forEach((element) { |
||||
element.isSelect = !allCheckIndex; |
||||
}); |
||||
allCheckIndex = !allCheckIndex; |
||||
setState(() {}); |
||||
}, |
||||
child: Text( |
||||
"全选", |
||||
style: TextStyle( |
||||
color: Color(0xFF000000), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
)), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.translucent, |
||||
onTap: () { |
||||
List<dynamic> ids = []; |
||||
records.forEach((element) { |
||||
if (element.isSelect) ids.add(element.id); |
||||
}); |
||||
if((double.tryParse(selectNum())??0) > 0) |
||||
Navigator.of(context) |
||||
.pushNamed('/router/edit_invoices_info',arguments:{ |
||||
"selectPrice": selectPrice(), |
||||
"ids":ids ?? [] |
||||
}).then((value) async{ |
||||
if(value ==1){ |
||||
_pageNum = 1; |
||||
records.clear(); |
||||
unRecords.clear(); |
||||
await _onRefresh(); |
||||
Future.delayed(Duration(milliseconds: 500), () { |
||||
SmartDialog.show( |
||||
widget: SettlementTips( |
||||
() {}, |
||||
text: "已成功提交发票信息", |
||||
), |
||||
); |
||||
}); |
||||
} |
||||
}); |
||||
}, |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: ((double.tryParse(selectNum()) ?? 0) > 0) |
||||
? Color(0xFF32A060) |
||||
: Color(0xFFd6d6d6), |
||||
borderRadius: BorderRadius.circular(4), |
||||
), |
||||
alignment: Alignment.center, |
||||
padding: EdgeInsets.symmetric( |
||||
horizontal: 23.w, vertical: 8.h), |
||||
child: Text( |
||||
"去开票", |
||||
style: TextStyle( |
||||
color: Colors.white, |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
), |
||||
) |
||||
], |
||||
), |
||||
], |
||||
), |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
///选中数量 |
||||
String selectNum() { |
||||
return unRecords.where((element) => element.isSelect).length.toString(); |
||||
} |
||||
|
||||
///选中的总价格 |
||||
String selectPrice() { |
||||
return unRecords |
||||
.where((element) => element.isSelect) |
||||
.fold( |
||||
0.0, |
||||
(previousValue, element) => |
||||
((double.tryParse(previousValue.toString()) ?? 0.0) + (double.tryParse(element.payedPrice ?? "0") ?? 0.0))) |
||||
.toStringAsFixed(2); |
||||
} |
||||
|
||||
///可开票订单list |
||||
Widget invoicesOrderItem(Records records) { |
||||
return Container( |
||||
padding: EdgeInsets.only(top: 12.h, bottom: 12.h, right: 20.w), |
||||
margin: EdgeInsets.symmetric(horizontal: 16.w, vertical: 6.h), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Color(0x0F06152E), |
||||
offset: Offset(0, 2), |
||||
blurRadius: 4, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
borderRadius: BorderRadius.circular(8), |
||||
), |
||||
child: Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
((double.tryParse(records?.payedPrice ?? "0") ?? 0) > 0) |
||||
? GestureDetector( |
||||
behavior: HitTestBehavior.translucent, |
||||
onTap: () { |
||||
setState(() { |
||||
records.isSelect = !records.isSelect; |
||||
}); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.only( |
||||
right: 15.w, left: 12.w, top: 5.h, bottom: 5.h), |
||||
alignment: Alignment.center, |
||||
child: Image.asset( |
||||
(records?.isSelect ?? false) |
||||
? "assets/image/icon_radio_selected.webp" |
||||
: "assets/image/icon_radio_unselected.webp", |
||||
width: 15.w, |
||||
height: 15.h, |
||||
), |
||||
), |
||||
) |
||||
: Container( |
||||
padding: EdgeInsets.only( |
||||
right: 15.w, left: 12.w, top: 5.h, bottom: 5.h), |
||||
alignment: Alignment.center, |
||||
child: Image.asset( |
||||
"assets/image/disenable_seletor_tow.webp", |
||||
width: 15.w, |
||||
height: 15.h, |
||||
)), |
||||
Expanded( |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Text( |
||||
records?.storeName ?? "", |
||||
maxLines: 2, |
||||
overflow: TextOverflow.ellipsis, |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
color: Color(0xFF0D0D0D), |
||||
), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.only(top: 8.h, bottom: 14.h), |
||||
child: Text( |
||||
"订单编号:${records?.id ?? ""}", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
color: Color(0xFF353535), |
||||
), |
||||
)), |
||||
Text( |
||||
"下单时间: ${records?.createTime ?? ""}", |
||||
style: TextStyle( |
||||
fontSize: 10.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
color: Color(0xFF0D0D0D), |
||||
), |
||||
), |
||||
], |
||||
)), |
||||
Text.rich( |
||||
TextSpan( |
||||
children: [ |
||||
TextSpan( |
||||
text: records?.finalPayPrice ?? "0.00", |
||||
style: TextStyle( |
||||
color: Color(0xFF000000), |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
TextSpan( |
||||
text: "元", |
||||
style: TextStyle( |
||||
color: Color(0xFF4D4D4D), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget invoicesOrderItemSm() { |
||||
return Container( |
||||
padding: EdgeInsets.only(top: 12, bottom: 12, left: 16), |
||||
margin: EdgeInsets.symmetric(horizontal: 16, vertical: 6), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Color(0x0F06152E), |
||||
offset: Offset(0, 2), |
||||
blurRadius: 4, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
borderRadius: BorderRadius.circular(8), |
||||
), |
||||
child: Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 13.w), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 16, |
||||
height: 16, |
||||
), |
||||
), |
||||
Expanded( |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 180, |
||||
height: 20, |
||||
), |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(top: 8.h, bottom: 14.h), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 182, |
||||
height: 17, |
||||
), |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 170, |
||||
height: 14, |
||||
), |
||||
) |
||||
], |
||||
)), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 13.w), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 49, |
||||
height: 20, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget noNetwork() { |
||||
return Container( |
||||
color: Colors.white, |
||||
width: double.infinity, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
networkError.substring(0, networkError.indexOf(",")), |
||||
style: TextStyle( |
||||
fontSize: 14, |
||||
color: Color(0xFF0D0D0D), |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(vertical: 10), |
||||
child: Text( |
||||
"请检查网络设置或稍后重试", |
||||
style: TextStyle( |
||||
fontSize: 12, |
||||
color: Color(0xFF7A797F), |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
_onRefresh(); |
||||
}, |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0xff32A060), |
||||
borderRadius: BorderRadius.circular(15), |
||||
), |
||||
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 3), |
||||
child: Text( |
||||
"重试", |
||||
style: TextStyle( |
||||
fontSize: 14, |
||||
color: Colors.white, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,577 @@
|
||||
import 'package:dio/dio.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter/services.dart'; |
||||
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
||||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
||||
import 'package:pull_to_refresh/pull_to_refresh.dart'; |
||||
import 'package:shared_preferences/shared_preferences.dart'; |
||||
import 'package:shimmer/shimmer.dart'; |
||||
|
||||
import '../../data/base_data.dart'; |
||||
import '../../data/title_info_list.dart'; |
||||
import '../../generated/l10n.dart'; |
||||
import '../../retrofit/retrofit_api.dart'; |
||||
import '../../utils/flutter_utils.dart'; |
||||
import '../../utils/font_weight.dart'; |
||||
import '../../view_widget/border_text.dart'; |
||||
import '../../view_widget/classic_header.dart'; |
||||
import '../../view_widget/my_appbar.dart'; |
||||
import '../../view_widget/my_footer.dart'; |
||||
import '../../view_widget/no_data_view.dart'; |
||||
import '../../view_widget/round_button.dart'; |
||||
|
||||
class InvoicesTitleInfo extends StatefulWidget { |
||||
final Map<String, dynamic>? arguments; |
||||
|
||||
InvoicesTitleInfo({this.arguments}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() { |
||||
return _InvoicesTitleInfo(); |
||||
} |
||||
} |
||||
|
||||
class _InvoicesTitleInfo extends State<InvoicesTitleInfo> { |
||||
final RefreshController refreshController = RefreshController(); |
||||
String networkError = ""; |
||||
int networkStatus = 0; |
||||
ApiService? apiService; |
||||
List<Records> records = []; |
||||
int _current = 1; |
||||
|
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
_onRefresh(); |
||||
} |
||||
|
||||
///离开页面记着销毁和清除 |
||||
@override |
||||
void dispose() { |
||||
super.dispose(); |
||||
refreshController.dispose(); |
||||
} |
||||
|
||||
_onRefresh({bool isShowLoad = true}) async { |
||||
if (isShowLoad) |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, |
||||
maskType: EasyLoadingMaskType.black); |
||||
await queryInvoiceHeadersList(); |
||||
EasyLoading.dismiss(); |
||||
if (!mounted) return; |
||||
if (refreshController.isRefresh) refreshController.refreshCompleted(); |
||||
setState(() {}); |
||||
} |
||||
|
||||
///查询抬头信心列表 |
||||
queryInvoiceHeadersList() async { |
||||
if (apiService == null) { |
||||
SharedPreferences value = await SharedPreferences.getInstance(); |
||||
apiService = ApiService( |
||||
Dio(), |
||||
context: context, |
||||
token: value.getString("token"), |
||||
); |
||||
} |
||||
BaseData<TitleInfoList>? baseData = await apiService?.invoiceHeaderList({ |
||||
"current": _current, |
||||
"map": {}, |
||||
"model": {}, |
||||
"order": "descending", |
||||
"size": 50, |
||||
"sort": "id" |
||||
}).catchError((error) { |
||||
networkError = AppUtils.dioErrorTypeToString(error.type); |
||||
networkStatus = -1; |
||||
setState(() {}); |
||||
refreshController.refreshFailed(); |
||||
refreshController.loadFailed(); |
||||
}); |
||||
if (!mounted) return; |
||||
if (baseData?.isSuccess ?? false) { |
||||
records.addAll(baseData?.data?.records ?? []); |
||||
if ((baseData?.data?.records ?? []).isEmpty || |
||||
records.length.toString() == baseData?.data?.total) |
||||
refreshController.loadNoData(); |
||||
else |
||||
refreshController.loadComplete(); |
||||
networkStatus = 1; |
||||
} else { |
||||
SmartDialog.showToast(baseData?.msg ?? "", alignment: Alignment.center); |
||||
} |
||||
} |
||||
|
||||
///删除抬头信息 |
||||
delTitleInfo(ids) async { |
||||
try { |
||||
EasyLoading.show( |
||||
status: S.current.zhengzaijiazai, |
||||
maskType: EasyLoadingMaskType.black); |
||||
if (apiService == null) { |
||||
SharedPreferences value = await SharedPreferences.getInstance(); |
||||
apiService = ApiService( |
||||
Dio(), |
||||
context: context, |
||||
token: value.getString("token"), |
||||
); |
||||
} |
||||
BaseData? baseData = await apiService?.delInvoiceHeader(ids).catchError((error) { |
||||
networkError = AppUtils.dioErrorTypeToString(error.type); |
||||
networkStatus = -1; |
||||
setState(() {}); |
||||
refreshController.refreshFailed(); |
||||
refreshController.loadFailed(); |
||||
}); |
||||
if (baseData?.isSuccess ??false) { |
||||
await editOnRefresh(); |
||||
Future.delayed(Duration(milliseconds: 500), () { |
||||
SmartDialog.showToast("删除信息成功", alignment: Alignment.center); |
||||
}); |
||||
networkStatus = 1; |
||||
} else { |
||||
SmartDialog.showToast("${baseData?.msg}", alignment: Alignment.center); |
||||
} |
||||
} finally { |
||||
EasyLoading.dismiss(); |
||||
} |
||||
} |
||||
|
||||
editOnRefresh() { |
||||
_current = 1; |
||||
records.clear(); |
||||
_onRefresh(isShowLoad: false); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
resizeToAvoidBottomInset: false, |
||||
appBar: MyAppBar( |
||||
title: "抬头管理", |
||||
titleColor: Colors.black, |
||||
background: Colors.white, |
||||
leadingColor: Colors.black, |
||||
), |
||||
body: networkStatus == -1 |
||||
? noNetwork() |
||||
: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Expanded( |
||||
child: Container( |
||||
child: SmartRefresher( |
||||
controller: refreshController, |
||||
enablePullDown: true, |
||||
// enablePullUp: records.length == 0 ? false : true, |
||||
header: MyHeader(), |
||||
footer: CustomFooter( |
||||
builder: (context, mode) { |
||||
return MyFooter(mode); |
||||
}, |
||||
), |
||||
onRefresh: () { |
||||
_current = 1; |
||||
records.clear(); |
||||
_onRefresh(isShowLoad: false); |
||||
}, |
||||
onLoading: () { |
||||
_current++; |
||||
_onRefresh(isShowLoad: false); |
||||
}, |
||||
physics: BouncingScrollPhysics(), |
||||
scrollController: ScrollController(), |
||||
child: Container( |
||||
margin: EdgeInsets.only(bottom: 20.h), |
||||
child: networkStatus == 0 |
||||
? ListView.builder( |
||||
itemCount: 10, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () {}, |
||||
child: titleInfoListSm(), |
||||
); |
||||
}, |
||||
) |
||||
: ((records == null || records.length == 0) |
||||
? NoDataView( |
||||
src: "assets/image/guan_zhu.webp", |
||||
isShowBtn: false, |
||||
text: "暂无抬头信息", |
||||
fontSize: 16, |
||||
margin: EdgeInsets.only(top:120), |
||||
) |
||||
: ListView.builder( |
||||
itemCount: records?.length ?? 0, |
||||
physics: BouncingScrollPhysics(), |
||||
shrinkWrap: true, |
||||
itemBuilder: (context, position) { |
||||
return GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
if(widget.arguments?["enterType"] == 0){ |
||||
Navigator.of(context).pop({ |
||||
"id":records[position].id ?? "", |
||||
"phone":records[position].companyPhone ?? "", |
||||
"name":records[position].name ?? "" |
||||
}); |
||||
}}, |
||||
child: titleInfoList(records[position]), |
||||
); |
||||
}, |
||||
))), |
||||
), |
||||
)), |
||||
if (networkStatus == 1) |
||||
GestureDetector( |
||||
onTap: () { |
||||
Navigator.of(context) |
||||
.pushNamed('/router/add_invoices_title',arguments:{ |
||||
"titleName":"添加抬头", |
||||
}).then((value) { |
||||
_current = 1; |
||||
records.clear(); |
||||
_onRefresh(isShowLoad: false); |
||||
}); |
||||
}, |
||||
child: Container( |
||||
padding: EdgeInsets.symmetric(vertical:16.h), |
||||
margin: EdgeInsets.only(bottom:25.h,left:20.w,right: 20.w), |
||||
decoration: BoxDecoration( |
||||
color: Color(0xff32A060), |
||||
borderRadius: BorderRadius.circular( |
||||
45 |
||||
), |
||||
), |
||||
width: double.infinity, |
||||
alignment: Alignment.center, |
||||
child: Text( |
||||
"添加抬头", |
||||
style: TextStyle( |
||||
color: Colors.white, |
||||
fontSize: 16.sp, |
||||
fontWeight: MyFontWeight.medium, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget titleInfoList(Records records) { |
||||
return Container( |
||||
padding: EdgeInsets.only( |
||||
top: ((records?.type ?? "") == "PERSONAL") ? 30.h : 14.h, |
||||
bottom: ((records?.type ?? "") == "PERSONAL") ? 30.h : 14.h, |
||||
left: 12.w), |
||||
margin: EdgeInsets.only(top: 12.h, bottom: 4.h, right: 14.w, left: 14.w), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Color(0x0F06152E), |
||||
offset: Offset(0, 2), |
||||
blurRadius: 4, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
borderRadius: BorderRadius.circular(8), |
||||
), |
||||
child: Row( |
||||
children: [ |
||||
Expanded( |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
records?.name ?? "", |
||||
maxLines: 1, |
||||
overflow: TextOverflow.ellipsis, |
||||
style: TextStyle( |
||||
color: Colors.black, |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.bold, |
||||
), |
||||
), |
||||
if ((records?.type ?? "") == "COMPANY") |
||||
Padding( |
||||
padding: EdgeInsets.only(top: 20.h), |
||||
child: Text( |
||||
"税号:${records?.taxId ?? ""}", |
||||
style: TextStyle( |
||||
color: Color(0xff353535), |
||||
fontSize: 14.sp, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
)), |
||||
], |
||||
)), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
Navigator.of(context).pushNamed('/router/add_invoices_title',arguments: { |
||||
"titleName":"编辑抬头", |
||||
"titleType":records.type == "COMPANY" ? 1:0, |
||||
"records":records, |
||||
}).then((value){ |
||||
if(value == 1) |
||||
editOnRefresh(); |
||||
}); |
||||
}, |
||||
child: Padding( |
||||
padding: EdgeInsets.only(left:30.w,right: 12.w), |
||||
child: Image.asset( |
||||
"assets/image/title_info_edit.webp", |
||||
width: 16.h, |
||||
height: 16.h, |
||||
fit: BoxFit.fitWidth, |
||||
))), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
showTitleInfoDialog(records?.id ?? ""); |
||||
}, |
||||
child: Padding( |
||||
padding: EdgeInsets.only(left: 12.w, right: 31.w), |
||||
child: Image.asset( |
||||
"assets/image/title_del.webp", |
||||
width: 15.h, |
||||
height: 16.h, |
||||
fit: BoxFit.fitWidth, |
||||
)), |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget titleInfoListSm() { |
||||
return Container( |
||||
padding: EdgeInsets.only(top: 12, bottom: 12, left: 16), |
||||
margin: EdgeInsets.symmetric(horizontal: 14, vertical: 6), |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
boxShadow: [ |
||||
BoxShadow( |
||||
color: Color(0x0F06152E), |
||||
offset: Offset(0, 2), |
||||
blurRadius: 4, |
||||
spreadRadius: 0, |
||||
) |
||||
], |
||||
borderRadius: BorderRadius.circular(8), |
||||
), |
||||
child: Row( |
||||
children: [ |
||||
Expanded( |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(bottom: 16), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 180.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 10), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 40.w, |
||||
height: 20.h, |
||||
), |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 120, |
||||
height: 20, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
], |
||||
)), |
||||
Row( |
||||
children: [ |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 24), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 16.w, |
||||
height: 16.h, |
||||
), |
||||
), |
||||
Shimmer.fromColors( |
||||
baseColor: Color(0XFFD8D8D8), |
||||
highlightColor: Color(0XFFD8D8D8), |
||||
child: Container( |
||||
margin: EdgeInsets.only(right: 25), |
||||
decoration: BoxDecoration( |
||||
color: Color(0XFFD8D8D8), |
||||
borderRadius: BorderRadius.circular(2), |
||||
), |
||||
width: 16, |
||||
height: 16, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Widget noNetwork() { |
||||
return Container( |
||||
width: double.infinity, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
// "无法连接到网络", |
||||
networkError.substring(0, networkError.indexOf(",")), |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Color(0xFF0D0D0D), |
||||
fontWeight: MyFontWeight.bold), |
||||
), |
||||
Padding( |
||||
padding: EdgeInsets.symmetric(vertical: 10.h), |
||||
child: Text( |
||||
"请检查网络设置或稍后重试", |
||||
style: TextStyle( |
||||
fontSize: 12.sp, |
||||
color: Color(0xFF7A797F), |
||||
fontWeight: MyFontWeight.regular), |
||||
), |
||||
), |
||||
GestureDetector( |
||||
behavior: HitTestBehavior.opaque, |
||||
onTap: () { |
||||
_onRefresh(); |
||||
}, |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
color: Color(0xff32A060), |
||||
borderRadius: BorderRadius.circular(15), |
||||
), |
||||
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 3.h), |
||||
child: Text( |
||||
"重试", |
||||
style: TextStyle( |
||||
fontSize: 14.sp, |
||||
color: Colors.white, |
||||
fontWeight: MyFontWeight.regular), |
||||
)), |
||||
) |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
//抬头信心删除提示弹窗 |
||||
showTitleInfoDialog(id) { |
||||
showDialog( |
||||
context: context, |
||||
builder: (context) { |
||||
return AlertDialog( |
||||
content: Container( |
||||
width: MediaQuery.of(context).size.width - 84, |
||||
height: 139, |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
"确认要删除这条数据吗?", |
||||
style: TextStyle( |
||||
color: Colors.black, |
||||
fontSize: 16, |
||||
fontWeight: MyFontWeight.regular, |
||||
), |
||||
), |
||||
SizedBox(height: 35), |
||||
Row( |
||||
children: [ |
||||
Expanded( |
||||
child: InkWell( |
||||
child: BorderText( |
||||
text: S.of(context).quxiao, |
||||
textColor: Color(0xff32A060), |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.bold, |
||||
borderColor: Color(0xff32A060), |
||||
radius: 4, |
||||
padding: EdgeInsets.all(12), |
||||
borderWidth: 1, |
||||
), |
||||
onTap: () { |
||||
Navigator.of(context).pop(); |
||||
}, |
||||
), |
||||
flex: 1, |
||||
), |
||||
SizedBox( |
||||
width: 16.w, |
||||
), |
||||
Expanded( |
||||
child: InkWell( |
||||
child: RoundButton( |
||||
text: S.of(context).shanchu, |
||||
textColor: Colors.white, |
||||
radius: 4, |
||||
padding: EdgeInsets.all(12), |
||||
backgroup: Color(0xff32A060), |
||||
fontSize: 16.sp, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
onTap: () { |
||||
delTitleInfo(id); |
||||
Navigator.of(context).pop(); |
||||
}, |
||||
), |
||||
flex: 1, |
||||
), |
||||
], |
||||
) |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,195 @@
|
||||
import 'dart:async'; |
||||
|
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter_pdfview/flutter_pdfview.dart'; |
||||
|
||||
class PDFScreen extends StatefulWidget { |
||||
final String? path; |
||||
final int? inlet; |
||||
|
||||
PDFScreen({Key? key,this.path,this.inlet}) : super(key: key); |
||||
|
||||
_PDFScreenState createState() => _PDFScreenState(); |
||||
} |
||||
|
||||
class _PDFScreenState extends State<PDFScreen> with WidgetsBindingObserver { |
||||
final Completer<PDFViewController> _controller = |
||||
Completer<PDFViewController>(); |
||||
int pages = 0; |
||||
int currentPage = 0; |
||||
int pageTotal = 0; |
||||
bool isReady = false; |
||||
String errorMessage = ''; |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return widget.inlet == 1 |
||||
? Material( |
||||
type: MaterialType.transparency, |
||||
child: Stack( |
||||
children: <Widget>[ |
||||
Center( |
||||
child: Container( |
||||
height: 250, |
||||
decoration: BoxDecoration( |
||||
color: Colors.white, |
||||
), |
||||
child: PDFView( |
||||
filePath: widget.path, |
||||
enableSwipe: true, |
||||
swipeHorizontal: true, |
||||
autoSpacing: false, |
||||
pageFling: true, |
||||
pageSnap: true, |
||||
defaultPage: currentPage, |
||||
fitPolicy: FitPolicy.BOTH, |
||||
preventLinkNavigation: false, |
||||
// if set to true the link is handled in flutter |
||||
onRender: (_pages) { |
||||
setState(() { |
||||
pages = _pages ?? 0; |
||||
isReady = true; |
||||
}); |
||||
}, |
||||
onError: (error) { |
||||
setState(() { |
||||
errorMessage = error.toString(); |
||||
}); |
||||
print(error.toString()); |
||||
}, |
||||
onPageError: (page, error) { |
||||
setState(() { |
||||
errorMessage = '$page: ${error.toString()}'; |
||||
}); |
||||
print('$page: ${error.toString()}'); |
||||
}, |
||||
onViewCreated: (PDFViewController pdfViewController) { |
||||
_controller.complete(pdfViewController); |
||||
}, |
||||
onLinkHandler: (String? uri) { |
||||
print('goto uri: $uri'); |
||||
}, |
||||
onPageChanged: (int? page, int? total) { |
||||
if ((total??0) > 0) { |
||||
print('page change: $page/$total'); |
||||
setState(() { |
||||
currentPage = page ?? 0; |
||||
pageTotal = total ??0; |
||||
}); |
||||
} else { |
||||
pageTotal = 1; |
||||
} |
||||
}, |
||||
), |
||||
), |
||||
), |
||||
errorMessage.isEmpty |
||||
? !isReady |
||||
? Center( |
||||
child: CircularProgressIndicator(), |
||||
) |
||||
: Container() |
||||
: Center( |
||||
child: Text(errorMessage), |
||||
), |
||||
//pdfindex显示 |
||||
Positioned( |
||||
width: MediaQuery.of(context).size.width, |
||||
bottom: 45, |
||||
child: Center( |
||||
child: Text("${currentPage + 1}/${(pageTotal > 0)?pageTotal:1}", |
||||
style: TextStyle(color: Colors.white, fontSize: 16)), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
) |
||||
: Scaffold( |
||||
body: Stack( |
||||
children: <Widget>[ |
||||
PDFView( |
||||
filePath: widget.path, |
||||
enableSwipe: true, |
||||
swipeHorizontal: true, |
||||
autoSpacing: false, |
||||
pageFling: true, |
||||
pageSnap: true, |
||||
defaultPage: currentPage, |
||||
fitPolicy: FitPolicy.BOTH, |
||||
preventLinkNavigation: false, |
||||
// if set to true the link is handled in flutter |
||||
onRender: (_pages) { |
||||
setState(() { |
||||
pages = _pages ?? 0; |
||||
isReady = true; |
||||
}); |
||||
}, |
||||
onError: (error) { |
||||
setState(() { |
||||
errorMessage = error.toString(); |
||||
}); |
||||
print(error.toString()); |
||||
}, |
||||
onPageError: (page, error) { |
||||
setState(() { |
||||
errorMessage = '$page: ${error.toString()}'; |
||||
}); |
||||
print('$page: ${error.toString()}'); |
||||
}, |
||||
onViewCreated: (PDFViewController pdfViewController) { |
||||
_controller.complete(pdfViewController); |
||||
}, |
||||
onLinkHandler: (String? uri) { |
||||
print('goto uri: $uri'); |
||||
}, |
||||
onPageChanged: (int? page, int? total) { |
||||
if ((total ?? 0) > 0) { |
||||
print('page change: $page/$total'); |
||||
setState(() { |
||||
currentPage = page ??0; |
||||
pageTotal = total ??0; |
||||
}); |
||||
} else { |
||||
pageTotal = 1; |
||||
} |
||||
}, |
||||
), |
||||
errorMessage.isEmpty |
||||
? !isReady |
||||
? Center( |
||||
child: CircularProgressIndicator(), |
||||
) |
||||
: Container() |
||||
: Center( |
||||
child: Text(errorMessage), |
||||
), |
||||
//pdfindex显示 |
||||
Positioned( |
||||
bottom: 45, |
||||
width: MediaQuery.of(context).size.width, |
||||
child: Center( |
||||
child: Text("${currentPage + 1}/${(pageTotal > 0)?pageTotal:1}", |
||||
style: TextStyle(color: Colors.black, fontSize: 16)), |
||||
), |
||||
), |
||||
Positioned( |
||||
//右上角关闭按钮 |
||||
right: 10, |
||||
top: MediaQuery.of(context).padding.top, |
||||
child: IconButton( |
||||
icon: Icon( |
||||
Icons.close, |
||||
size: 30, |
||||
color: Colors.black, |
||||
), |
||||
onPressed: () { |
||||
Navigator.of(context).pop(); |
||||
}, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
Loading…
Reference in new issue