Marking.Client.Moblie/marking_app/lib/pages/marking/progress.dart

456 lines
16 KiB
Dart

/*
* @Author: wangyang 1147192855@qq.com
* @Date: 2022-07-15 09:14:59
* @LastEditors: wangyang 1147192855@qq.com
* @LastEditTime: 2022-07-29 10:22:25
* @FilePath: \marking_app\lib\pages\marking\progress.dart
* @Description: 进度页面
*/
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:marking_app/common/config/request_config.dart';
import 'package:marking_app/utils/index.dart';
import 'package:marking_app/utils/my_text.dart';
import 'package:marking_app/utils/request/rest_client.dart';
import 'package:marking_app/common/mixin/common.dart';
import 'package:marking_app/common/model/common/base_page_data.dart';
import 'package:marking_app/common/model/common/base_structure_result.dart';
import 'package:marking_app/common/model/progress/progress_item.dart';
import 'package:marking_app/common/model/progress/progress_page_params.dart';
import 'package:marking_app/common/model/progress/progress_statistics.dart';
import 'package:marking_app/utils/easy_refresh/mixin/refresh_data_handle.dart';
import 'package:percent_indicator/linear_percent_indicator.dart';
class Progress extends StatefulWidget {
final String name;
final int examSubjectId;
const Progress(this.examSubjectId, this.name, {Key? key}) : super(key: key);
@override
State<Progress> createState() => ProgressState();
}
class ProgressState extends State<Progress>
with SingleTickerProviderStateMixin, CommonMixin, RefreshDataHandle<ProgressItem, ProgressPageParams> {
late final String name;
late final int examSubjectId;
late ProgressPageParams pageParams;
List<ProgressItem> listData = [];
ProgressStatistics statisticsData = ProgressStatistics(0, 0, 0, 0, 0); /* 发起请求获取统计数据 */
late final EasyRefreshController _refreshController;
/*
* 获取统计数据
* getDataForStatistics
*/
void getDataForStatistics() async {
RestClient client = await getClient();
BaseStructureResult<ProgressStatistics> result = await client.getProgressStatistics(examSubjectId.toString());
if (result.code == RequestConfig.successCode) {
toUpState(setState, () => statisticsData = result.data!, mounted);
}
}
/*
* 获取分页数据
* getDataForPageData
*/
void getDataForPageData(EasyRefreshController controller, {bool isReFresh = false}) async {
RestClient client = await getClient();
BasePageData<ProgressItem>? results = await toRefreshDataWithPath(
controller,
api: client.getProgressByPage,
params: pageParams,
pahtVal: examSubjectId.toString(),
isReFresh: isReFresh,
context: context,
);
if (results != null && results.items.isNotEmpty) {
if (isReFresh) {
setState(() => listData = results.items);
} else {
setState(() => listData.addAll(results.items));
}
}
}
@override
void initState() {
name = widget.name;
examSubjectId = widget.examSubjectId;
pageParams = ProgressPageParams(examSubjectId: examSubjectId, page: 1, limit: 10);
_refreshController = EasyRefreshController();
getDataForStatistics();
super.initState();
}
@override
void dispose() {
_refreshController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnnotatedRegion(
value: const SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
systemNavigationBarIconBrightness: Brightness.light,
statusBarIconBrightness: Brightness.light,
statusBarBrightness: Brightness.dark,
),
child: Stack(
children: [
SizedBox(
height: double.infinity,
child: Column(
children: [
Container(
height: 200.h,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/personal_bgi.png'),
fit: BoxFit.cover,
),
),
),
Expanded(
child: Container(
color: const Color.fromRGBO(248, 248, 248, 1),
),
)
],
),
),
Scaffold(
backgroundColor: Colors.transparent,
appBar: PreferredSize(
preferredSize: Size.fromHeight(40.h),
child: AppBar(
title: quickText(
'$name进度',
size: 18.sp,
color: Colors.white,
),
elevation: 0,
backgroundColor: Colors.transparent,
),
),
body: EasyRefresh(
firstRefresh: true,
taskIndependence: true,
enableControlFinishLoad: true,
enableControlFinishRefresh: true,
controller: _refreshController,
onRefresh: () async => getDataForPageData(_refreshController, isReFresh: true),
onLoad: () async {
pageParams.page += 1;
getDataForPageData(_refreshController);
},
header: DeliveryHeader(),
footer: MaterialFooter(),
child: ListView(
padding: EdgeInsets.only(left: 16.w, right: 16.w, top: 14.h),
children: [_StatisticsInfo(widget.name, statisticsData), ...listData.map((e) => _DataItem(e))],
),
),
),
],
),
);
}
}
// 统计情况
// ignore: must_be_immutable
class _StatisticsInfo extends StatelessWidget {
String name;
ProgressStatistics theData;
_StatisticsInfo(this.name, this.theData, {Key? key}) : super(key: key);
final TextStyle ts2 = TextStyle(
fontSize: 12.sp,
color: const Color.fromRGBO(148, 163, 182, 1),
);
final TextStyle ts1 = TextStyle(
fontSize: 18.sp,
color: const Color.fromRGBO(45, 56, 76, 1),
);
@override
Widget build(BuildContext context) {
TextStyle ts11 = TextStyle(
fontSize: 18.sp,
color: Theme.of(context).primaryColor,
);
double myAverage = theData.myAverage;
double overallAverage = theData.overallAverage;
double comparison = myAverage - overallAverage; // 比较情况
String imageUrl;
if (comparison > 0) {
imageUrl = 'assets/images/rise.png';
} else if (comparison < 0) {
imageUrl = 'assets/images/fall.png';
} else {
imageUrl = 'assets/images/equal.png';
}
Image comparisonImg = Image.asset(imageUrl, fit: BoxFit.cover, width: 10.w, height: 10.w);
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 20.h),
height: 194.h,
margin: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(6.w)),
boxShadow: [
BoxShadow(
color: const Color.fromRGBO(46, 91, 255, 0.1),
offset: Offset(6.w, 10.h), //阴影y轴偏移量
blurRadius: 14, //阴影模糊程度
spreadRadius: 0.5, //阴影扩散程度
)
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name,
textAlign: TextAlign.left,
style: TextStyle(fontSize: 14.sp, color: const Color.fromRGBO(45, 56, 76, 1)),
),
Expanded(
child: Container(
margin: EdgeInsets.only(top: 18.h),
child: Row(
children: [
Stack(
alignment: const FractionalOffset(0.5, 0.5),
children: [
SizedBox(
width: 96.w,
height: 96.w,
child: theData.markingTotal == 0
? null
: CircularProgressIndicator(
backgroundColor: const Color.fromRGBO(217, 225, 255, 1),
valueColor: AlwaysStoppedAnimation(Theme.of(context).primaryColor),
value: theData.completionRate,
strokeWidth: 9.w),
),
Column(
mainAxisSize: MainAxisSize.min,
children: [
quickText(
'${theData.completionRateStr}%',
size: 20.sp,
color: Theme.of(context).primaryColor,
),
quickText(
'整体进度',
size: 10.sp,
color: const Color.fromRGBO(148, 163, 182, 1),
)
],
),
],
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
children: [
Text('${theData.markingFinishedCount}', style: ts1),
Container(height: 3.h),
Text('已阅总量', style: ts2),
],
),
Column(
children: [
Text('${theData.markingUnfinishedCount}', style: ts11),
Container(height: 3.h),
Text('待阅总量', style: ts2),
],
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
children: [
Text(overallAverage.toStringAsFixed(2), style: ts1),
Container(height: 3.h),
Text('整体均分', style: ts2),
],
),
Stack(
alignment: const FractionalOffset(1.7, 0.4),
children: [
Column(
children: [
Text(myAverage.toStringAsFixed(2), style: ts11),
Container(height: 3.h),
Text('我的平均分', style: ts2),
],
),
Column(
mainAxisSize: MainAxisSize.min,
children: [
comparisonImg,
Container(height: 1.h),
Text(
(overallAverage - myAverage).toStringAsFixed(2),
style: TextStyle(
fontSize: 9.sp,
color: const Color.fromRGBO(148, 163, 182, 1),
),
),
],
)
],
)
],
)
],
),
)
],
),
))
],
),
);
}
}
// 数据单个详情
class _DataItem extends StatelessWidget {
ProgressItem item;
_DataItem(this.item, {Key? key}) : super(key: key);
GlobalKey _redKey = GlobalKey();
@override
Widget build(BuildContext context) {
return Container(
height: 100.h,
margin: EdgeInsets.only(top: 12.h),
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(6.w)),
boxShadow: [
BoxShadow(
color: const Color.fromRGBO(46, 91, 255, 0.1),
offset: Offset(6.w, 4.h), //阴影y轴偏移量
blurRadius: 8, //阴影模糊程度
spreadRadius: 0.3, //阴影扩散程度
)
],
),
child: Column(
// crossAxisAlignment: C,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Row(
children: [
Text(
'${item.teacherName}老师',
style: TextStyle(
color: const Color.fromRGBO(45, 56, 76, 1),
fontWeight: FontWeight.w700,
fontSize: 14.sp,
),
),
Container(
margin: EdgeInsets.only(left: 14.w),
child: Row(
children: [
Text(
'评阅均分:',
style: TextStyle(
color: const Color.fromRGBO(46, 91, 255, 1),
fontSize: 12.sp,
),
),
Text(
item.avgScore.toStringAsFixed(2),
style: TextStyle(
color: const Color.fromRGBO(46, 91, 255, 1),
fontSize: 12.sp,
),
),
],
),
)
],
)),
Text(
item.schoolName,
style: TextStyle(
fontSize: 12.sp,
color: const Color.fromRGBO(148, 163, 182, 1),
),
)
],
),
Padding(
padding: EdgeInsets.only(bottom: 8.h),
child: Row(
children: [
Expanded(
child: LinearPercentIndicator(
padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 0),
// width: MediaQuery.of(context).size.width - 50,
animation: true,
lineHeight: 10.h,
animationDuration: 2500,
percent: item.completionRate,
center: quickText(
'${item.completionRateStr}%',
size: 10.sp,
color: Colors.white,
),
// linearStrokeCap: LinearStrokeCap.butt,
progressColor: Theme.of(context).primaryColor,
backgroundColor: const Color.fromRGBO(219, 224, 243, 1),
barRadius: Radius.circular(10.h)),
),
Container(
margin: EdgeInsets.only(left: 14.w),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
quickText(item.finishCount.toString(), size: 12.sp, color: Theme.of(context).primaryColor),
quickText('/', size: 12.sp, color: const Color.fromRGBO(148, 163, 182, 1)),
quickText(item.totalCount.toString(), size: 12.sp, color: const Color.fromRGBO(148, 163, 182, 1)),
],
),
)
],
),
)
],
),
);
}
}