Compare commits

...

86 Commits
t ... main

Author SHA1 Message Date
1147192855@qq.com 068cbbe550 no message 2024-06-27 11:06:48 +08:00
1147192855@qq.com 41bfa32ad6 no message 2024-06-25 09:55:00 +08:00
1147192855@qq.com 4eb28224d3 no message 2024-06-21 10:03:30 +08:00
豌杂 fc3f656c66 提交1888账号登陆 2024-06-18 11:48:51 +08:00
豌杂 c9edeb662f IOS 版本号提交 2024-06-17 10:48:14 +08:00
1147192855@qq.com e05d7c4395 no message 2024-06-13 17:23:07 +08:00
1147192855@qq.com c75f0f191c no message 2024-06-13 17:08:14 +08:00
1147192855@qq.com 28a03f1cde 更新登录choice学校功能 2024-06-13 17:01:15 +08:00
1147192855@qq.com b3b58fb55f no message 2024-06-13 14:38:43 +08:00
1147192855@qq.com 8ed3b85b92 处理登录添加所在学校下拉框 2024-06-13 14:35:12 +08:00
1147192855@qq.com a7bdfe9af7 no message 2024-05-21 14:37:19 +08:00
豌杂 5d10205abb no message 2024-05-20 16:48:57 +08:00
1147192855@qq.com 88dd4c4c16 Merge branch 'marking_annotations_04_29' 2024-05-20 15:34:34 +08:00
1147192855@qq.com bf0a5f5ff1 no message 2024-05-20 15:34:14 +08:00
1147192855@qq.com c955f1859a no message 2024-05-20 10:48:12 +08:00
1147192855@qq.com 1f2e5dbb56 完成 作业首页更改和作业笔迹还原默认两倍速 和查看原稿功能 2024-05-17 15:41:04 +08:00
1147192855@qq.com 8287518fc1 no message 2024-05-15 14:00:37 +08:00
1147192855@qq.com f13bdbcf5f no message 2024-05-14 18:17:15 +08:00
1147192855@qq.com 6dca9d8f0e 处理视图缩放变小坐标问题 2024-05-14 16:17:50 +08:00
1147192855@qq.com b52c335c65 完成升级APP功能 2024-05-14 13:53:17 +08:00
1147192855@qq.com 309c708847 no message 2024-05-13 18:42:41 +08:00
1147192855@qq.com e727cb3d20 no message 2024-05-13 14:50:07 +08:00
1147192855@qq.com ad660bec11 no message 2024-05-10 19:26:59 +08:00
1147192855@qq.com adc07a9346 no message 2024-05-10 10:23:47 +08:00
1147192855@qq.com a13cab2c96 基本完成工作 2024-05-09 19:55:25 +08:00
1147192855@qq.com 060ac01fde 初步完成当前任务,还剩下放大后批阅 2024-05-08 16:52:04 +08:00
1147192855@qq.com eb65701324 no message 2024-05-07 19:25:16 +08:00
1147192855@qq.com a15e47cfcd no message 2024-05-06 09:10:50 +08:00
1147192855@qq.com 84f9d7a4ea no message 2024-05-06 08:59:21 +08:00
豌杂 cf7870c05f no message 2024-04-29 11:34:49 +08:00
1147192855@qq.com 03a52f5715 no message 2024-04-29 11:12:54 +08:00
1147192855@qq.com afeb05272e no message 2024-04-28 13:47:29 +08:00
machuanyu 3944a72ab6 Merge branch 'mcy' into main
# Conflicts:
#	marking_app/lib/routes/RouterManager.dart
2024-04-28 11:45:58 +08:00
豌杂 ab6546a7af no message 2024-04-28 11:01:34 +08:00
1147192855@qq.com fff1bb5639 no message 2024-04-28 10:45:56 +08:00
1147192855@qq.com a636819fda Merge branch 'job_new_demand'
# Conflicts:
#	marking_app/lib/routes/RouterManager.dart
#	marking_app/lib/utils/request/rest_client.dart
2024-04-28 10:38:32 +08:00
1147192855@qq.com 89e15ba672 no message 2024-04-28 09:28:57 +08:00
1147192855@qq.com 8ab319c32e no message 2024-04-26 18:08:46 +08:00
machuanyu 8d1de06f14 注册,注销账号 2024-04-26 17:31:03 +08:00
1147192855@qq.com 17738ff29e no message 2024-04-25 14:33:06 +08:00
1147192855@qq.com 919f71f28b no message 2024-04-25 10:59:37 +08:00
1147192855@qq.com 3666bea6bd no message 2024-04-24 18:24:17 +08:00
1147192855@qq.com 3a6e220f5e no message 2024-04-24 18:10:18 +08:00
machuanyu 23bd9501ff bug修改 2024-04-24 16:43:08 +08:00
1147192855@qq.com 8c10e6eb4d no message 2024-04-24 13:46:19 +08:00
machuanyu 83e328ceb8 报告 2024-04-22 14:25:41 +08:00
1147192855@qq.com 02cb205126 no message 2024-04-19 14:12:04 +08:00
1147192855@qq.com 8c800e1d1c no message 2024-04-19 13:48:06 +08:00
1147192855@qq.com aa9dd3d83c 轨迹页面 2024-04-17 18:15:37 +08:00
machuanyu 1fbb102370 Merge branch 'mcy_revision' into job_new_demand 2024-04-17 17:13:53 +08:00
machuanyu a759583ca0 答题轨迹按作业详情 2024-04-17 17:13:24 +08:00
1147192855@qq.com e33e3cfac3 no message 2024-04-17 16:04:48 +08:00
1147192855@qq.com 0c3b3f8719 Merge branch 'main' into job_new_demand 2024-04-17 11:00:28 +08:00
1147192855@qq.com 0cb3d69201 no message 2024-04-17 10:59:45 +08:00
1147192855@qq.com 8b4f38558f 调整隐私政策和用户协议 2024-04-17 10:54:53 +08:00
machuanyu 1494e69b56 Merge branch 'mcy_revision' into job_new_demand 2024-04-17 09:02:07 +08:00
machuanyu fbebdbc428 答题轨迹 2024-04-17 09:01:41 +08:00
1147192855@qq.com 491cad7955 no message 2024-04-16 18:12:48 +08:00
1147192855@qq.com 1697f59d43 no message 2024-04-16 17:49:46 +08:00
1147192855@qq.com dd033fd20f Merge branch 'main' into job_new_demand
# Conflicts:
#	marking_app/lib/pages/mainPage.dart
2024-04-16 17:44:21 +08:00
1147192855@qq.com dc53062556 no message 2024-04-16 17:38:31 +08:00
1147192855@qq.com fb23ba02d1 添加用户协议框和隐私框 2024-04-16 16:16:30 +08:00
machuanyu 21183f11bc Merge branch 'job_new_demand' into mcy_revision
# Conflicts:
#	marking_app/lib/pages/homework_correction/job_home.dart
2024-04-16 13:47:19 +08:00
machuanyu 0c54c16865 答题轨迹 2024-04-16 13:44:34 +08:00
1147192855@qq.com d9adbe845b no message 2024-04-16 12:05:27 +08:00
1147192855@qq.com 4c78d903a1 Merge branch 'main' into job_new_demand
# Conflicts:
#	.gitignore
2024-04-15 18:22:40 +08:00
1147192855@qq.com 727c774ea0 no message 2024-04-15 18:16:52 +08:00
1147192855@qq.com 4e812bc5c0 no message 2024-04-15 15:41:13 +08:00
1147192855@qq.com 6e2010a7cc no message 2024-04-15 14:15:48 +08:00
豌杂 abb0d41d39 no message 2024-04-15 14:04:20 +08:00
machuanyu 42d2e4ab39 历史作业 2024-04-15 13:47:26 +08:00
1147192855@qq.com a614c90458 no message 2024-04-15 13:40:43 +08:00
1147192855@qq.com c43e75fafd 处理无法切换下一题BUG 2024-04-15 11:47:28 +08:00
1147192855@qq.com ecfb2c33b6 更新此次批阅优化问题 2024-04-12 12:20:36 +08:00
machuanyu 994ca04988 Merge branch 'job_new_demand' into mcy_revision 2024-04-12 11:23:53 +08:00
machuanyu e22d5f2655 知识点详情 2024-04-12 11:22:27 +08:00
1147192855@qq.com d5249ba0af 处理异常 2024-04-12 10:03:42 +08:00
1147192855@qq.com 326a2fe99e no message 2024-04-11 17:31:02 +08:00
machuanyu 5cdf645f86 -- 2024-04-11 17:24:00 +08:00
machuanyu 7e3c6882e9 合并代码 2024-04-11 17:19:21 +08:00
machuanyu 794e4d6cbe Merge branch 'mcy_revision' into job_new_demand
# Conflicts:
#	marking_app/lib/routes/RouterManager.dart
2024-04-11 17:18:15 +08:00
machuanyu 991ec9310e 知识点掌握 2024-04-11 17:15:27 +08:00
1147192855@qq.com f63c1ea678 Merge branch 'mcy_revision' of https://gitea.23544.com/marking/Marking.Client.Moblie into job_new_demand 2024-04-11 16:12:27 +08:00
1147192855@qq.com 74c8148305 no message 2024-04-11 15:53:31 +08:00
1147192855@qq.com ee41ad7d1b 添加作业首页 2024-04-11 15:53:04 +08:00
1147192855@qq.com 5a43ccffcf no message 2024-04-11 14:29:27 +08:00
113 changed files with 8937 additions and 1939 deletions

17
.gitignore vendored
View File

@ -214,3 +214,20 @@ marking_app/lib/pages/homework_correction/job_personal_detail.g.dart
marking_app/lib/common/model/event_bus/jobs/job_do_papers_submit_check_switch_bus.g.dart
marking_app/lib/common/model/event_bus/jobs/job_do_synchro_tab.g.dart
marking_app/lib/pages/homework_correction/widget/top_count.g.dart
marking_app/lib/common/model/event_bus/job_home_refresh_bus.g.dart
marking_app/lib/common/model/job/job_knowledge_points_detail.g.dart
marking_app/lib/common/model/job/job_knowledge_points.g.dart
marking_app/lib/pages/homework_correction/job_knowledge_points.g.dart
marking_app/lib/pages/homework_correction/job_knowledge_points_detail.g.dart
marking_app/lib/common/model/job/job_knowledge_detail_student.g.dart
marking_app/lib/common/model/job/job_knowledge_detail_student.g.dart
marking_app/lib/pages/homework_correction/job_home.g.dart
marking_app/lib/common/model/marking/keyboard_assist_event.g.dart
marking_app/lib/common/model/marking/marking_history_zoom_info.g.dart
marking_app/lib/common/model/job/job_handwriting.g.dart
marking_app/lib/utils/my_time_util.g.dart
marking_app/lib/pages/homework_correction/widget/answer_handwriting.g.dart
marking_app/lib/pages/report_detail/report_history.g.dart
marking_app/lib/common/model/report/report_student_history_record.g.dart
marking_app/lib/common/model/report/report_student_info.g.dart
marking_app/lib/pages/login/index.g.dart

View File

@ -14,3 +14,7 @@ A few resources to get you started if this is your first Flutter project:
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
fvm flutter build apk --release --no-tree-shake-icons

View File

@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.marking_app">
<application
android:label="学而有道"
android:label="学而有道阅卷"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
@ -35,7 +35,14 @@
android:name="flutterEmbedding"
android:value="2" />
<!-- Provider -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" />
</provider>
</application>
<!-- 访问电话状态 -->
@ -47,8 +54,10 @@
<!-- 获取当前WiFi接入的状态以及WLAN热点的信息 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 获取当前设备存储权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACTION_MANAGE_UNKNOWN_APP_SOURCES"/>
<!-- 这个权限用于app安装 -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<!-- 屏幕常亮权限 -->
@ -58,4 +67,6 @@
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"/>
<!-- Permissions options for the `notification` group -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
</manifest>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path path="Android/data/com.example.marking_app/" name="files_root" />
<external-path path="." name="external_storage_root" />
</paths>

View File

@ -13,9 +13,13 @@
<!-- 获取当前WiFi接入的状态以及WLAN热点的信息 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 获取当前设备存储权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> -->
<!-- <uses-permission android:name="android.permission.INTERNET"/> -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<!-- 这个权限用于app安装 -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.CAMERA"/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 724 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 B

View File

@ -1,4 +1,6 @@
PODS:
- app_installer (1.1.0):
- Flutter
- connectivity_plus (0.0.1):
- Flutter
- ReachabilitySwift
@ -37,6 +39,7 @@ PODS:
- Flutter
DEPENDENCIES:
- app_installer (from `.symlinks/plugins/app_installer/ios`)
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
- Flutter (from `Flutter`)
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
@ -59,6 +62,8 @@ SPEC REPOS:
- Toast
EXTERNAL SOURCES:
app_installer:
:path: ".symlinks/plugins/app_installer/ios"
connectivity_plus:
:path: ".symlinks/plugins/connectivity_plus/ios"
Flutter:
@ -91,6 +96,7 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
SPEC CHECKSUMS:
app_installer: 4301996bd8f3c6f75776416b8885a6d92928306f
connectivity_plus: 413a8857dd5d9f1c399a39130850d02fe0feaf7e
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069
@ -111,4 +117,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: 64629b724b9886c2d78e6972ff5ef90e370df047
COCOAPODS: 1.11.3
COCOAPODS: 1.12.1

View File

@ -16,6 +16,177 @@
EE3BAAE20F3BEC99D310EC6B /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AE64B664D96A59005B338D3 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
0B2156402C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3E842772C2699BC8F65359A06505C5A5;
remoteInfo = app_installer;
};
0B2156422C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 6D3FD4746C5C4B5292B7C4C862F01EF9;
remoteInfo = connectivity_plus;
};
0B2156442C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 95AEC45023DC633BFEBFE200DD4C81FC;
remoteInfo = flutter_keyboard_visibility;
};
0B2156462C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = D0C5A85ABEF5ED03A54A449B87B69225;
remoteInfo = fluttertoast;
};
0B2156482C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 768975E636D1D2FB85622FB67DB04E5A;
remoteInfo = image_picker_ios;
};
0B21564A2C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = F0C7EFBFF01CFAAB52BA74E6CB40CE2C;
remoteInfo = "image_picker_ios-image_picker_ios_privacy";
};
0B21564C2C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 723F1D07DBDF0EC2E0D163A4996FEE3D;
remoteInfo = install_plugin;
};
0B21564E2C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 6E45859F778E298A6DDE318300ACC4C5;
remoteInfo = package_info;
};
0B2156502C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = AE157A33FEF959A214796BFF348717F6;
remoteInfo = path_provider_foundation;
};
0B2156522C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3DBD4BADE27F8B91024E4B4B4DD75DB5;
remoteInfo = "path_provider_foundation-path_provider_foundation_privacy";
};
0B2156542C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = C7AD28D5FB25A8DEDF61F78996932FA6;
remoteInfo = permission_handler_apple;
};
0B2156562C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 669E8F25E1897672BDB80B7EB784DA24;
remoteInfo = "Pods-Runner";
};
0B2156582C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 21B03CA622E690725A6626C088E1D09F;
remoteInfo = ReachabilitySwift;
};
0B21565A2C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = DE8135CAE607F7824D08D08BDA5968B9;
remoteInfo = rive_common;
};
0B21565C2C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 93C6A45C6E4792269BE9BE0073839BF0;
remoteInfo = shared_preferences_foundation;
};
0B21565E2C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 0652FCE3FC19056983AABE058B3CC45B;
remoteInfo = "shared_preferences_foundation-shared_preferences_foundation_privacy";
};
0B2156602C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = B799BFFEC5B11F90F501202080A57F37;
remoteInfo = sqflite;
};
0B2156622C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 58497E6EB70BA49D9A885C22D09B7A7C;
remoteInfo = "sqflite-sqflite_darwin_privacy";
};
0B2156642C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 55E0AFD333353D71ACC2207149E879D6;
remoteInfo = Toast;
};
0B2156662C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 7B7C06D35B3BC2BD649AAA1A489E49DA;
remoteInfo = url_launcher_ios;
};
0B2156682C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = DBA6F34C072B134D3BE38983776DD1C3;
remoteInfo = "url_launcher_ios-url_launcher_ios_privacy";
};
0B21566A2C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 315E7D4955EFF42177E9BBC4382B527F;
remoteInfo = wakelock;
};
0B21566C2C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 7409A9316D1EEFAC7B383BE8CEC1BE03;
remoteInfo = webview_flutter_wkwebview;
};
0B21566E2C0D8FFF00D5A718 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 163A707D53693953E4DC7E0DE4C912A4;
remoteInfo = "webview_flutter_wkwebview-webview_flutter_wkwebview_privacy";
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
@ -30,6 +201,7 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Pods.xcodeproj; path = Pods/Pods.xcodeproj; sourceTree = "<group>"; };
0BD0304F2994F44800EB7527 /* Launch Screen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
@ -64,11 +236,43 @@
050DAC6E1AD50AF47A1F4114 /* Frameworks */ = {
isa = PBXGroup;
children = (
0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */,
9AE64B664D96A59005B338D3 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
0B2156252C0D8FFF00D5A718 /* Products */ = {
isa = PBXGroup;
children = (
0B2156412C0D8FFF00D5A718 /* app_installer */,
0B2156432C0D8FFF00D5A718 /* connectivity_plus */,
0B2156452C0D8FFF00D5A718 /* flutter_keyboard_visibility */,
0B2156472C0D8FFF00D5A718 /* fluttertoast */,
0B2156492C0D8FFF00D5A718 /* image_picker_ios */,
0B21564B2C0D8FFF00D5A718 /* image_picker_ios-image_picker_ios_privacy */,
0B21564D2C0D8FFF00D5A718 /* install_plugin */,
0B21564F2C0D8FFF00D5A718 /* package_info */,
0B2156512C0D8FFF00D5A718 /* path_provider_foundation */,
0B2156532C0D8FFF00D5A718 /* path_provider_foundation-path_provider_foundation_privacy */,
0B2156552C0D8FFF00D5A718 /* permission_handler_apple */,
0B2156572C0D8FFF00D5A718 /* Pods-Runner */,
0B2156592C0D8FFF00D5A718 /* ReachabilitySwift */,
0B21565B2C0D8FFF00D5A718 /* rive_common */,
0B21565D2C0D8FFF00D5A718 /* shared_preferences_foundation */,
0B21565F2C0D8FFF00D5A718 /* shared_preferences_foundation-shared_preferences_foundation_privacy */,
0B2156612C0D8FFF00D5A718 /* sqflite */,
0B2156632C0D8FFF00D5A718 /* sqflite-sqflite_darwin_privacy */,
0B2156652C0D8FFF00D5A718 /* Toast */,
0B2156672C0D8FFF00D5A718 /* url_launcher_ios */,
0B2156692C0D8FFF00D5A718 /* url_launcher_ios-url_launcher_ios_privacy */,
0B21566B2C0D8FFF00D5A718 /* wakelock */,
0B21566D2C0D8FFF00D5A718 /* webview_flutter_wkwebview */,
0B21566F2C0D8FFF00D5A718 /* webview_flutter_wkwebview-webview_flutter_wkwebview_privacy */,
);
name = Products;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
@ -175,6 +379,12 @@
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = 0B2156252C0D8FFF00D5A718 /* Products */;
ProjectRef = 0B2156242C0D8FFF00D5A718 /* Pods.xcodeproj */;
},
);
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
@ -182,6 +392,201 @@
};
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
0B2156412C0D8FFF00D5A718 /* app_installer */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
name = app_installer;
path = app_installer.framework;
remoteRef = 0B2156402C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B2156432C0D8FFF00D5A718 /* connectivity_plus */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
name = connectivity_plus;
path = connectivity_plus.framework;
remoteRef = 0B2156422C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B2156452C0D8FFF00D5A718 /* flutter_keyboard_visibility */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
name = flutter_keyboard_visibility;
path = flutter_keyboard_visibility.framework;
remoteRef = 0B2156442C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B2156472C0D8FFF00D5A718 /* fluttertoast */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
name = fluttertoast;
path = fluttertoast.framework;
remoteRef = 0B2156462C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B2156492C0D8FFF00D5A718 /* image_picker_ios */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
name = image_picker_ios;
path = image_picker_ios.framework;
remoteRef = 0B2156482C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B21564B2C0D8FFF00D5A718 /* image_picker_ios-image_picker_ios_privacy */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
name = "image_picker_ios-image_picker_ios_privacy";
path = image_picker_ios_privacy.bundle;
remoteRef = 0B21564A2C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B21564D2C0D8FFF00D5A718 /* install_plugin */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
name = install_plugin;
path = install_plugin.framework;
remoteRef = 0B21564C2C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B21564F2C0D8FFF00D5A718 /* package_info */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
name = package_info;
path = package_info.framework;
remoteRef = 0B21564E2C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B2156512C0D8FFF00D5A718 /* path_provider_foundation */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
name = path_provider_foundation;
path = path_provider_foundation.framework;
remoteRef = 0B2156502C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B2156532C0D8FFF00D5A718 /* path_provider_foundation-path_provider_foundation_privacy */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
name = "path_provider_foundation-path_provider_foundation_privacy";
path = path_provider_foundation_privacy.bundle;
remoteRef = 0B2156522C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B2156552C0D8FFF00D5A718 /* permission_handler_apple */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
name = permission_handler_apple;
path = permission_handler_apple.framework;
remoteRef = 0B2156542C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B2156572C0D8FFF00D5A718 /* Pods-Runner */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
name = "Pods-Runner";
path = Pods_Runner.framework;
remoteRef = 0B2156562C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B2156592C0D8FFF00D5A718 /* ReachabilitySwift */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
name = ReachabilitySwift;
path = Reachability.framework;
remoteRef = 0B2156582C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B21565B2C0D8FFF00D5A718 /* rive_common */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
name = rive_common;
path = rive_common.framework;
remoteRef = 0B21565A2C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B21565D2C0D8FFF00D5A718 /* shared_preferences_foundation */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
name = shared_preferences_foundation;
path = shared_preferences_foundation.framework;
remoteRef = 0B21565C2C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B21565F2C0D8FFF00D5A718 /* shared_preferences_foundation-shared_preferences_foundation_privacy */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
name = "shared_preferences_foundation-shared_preferences_foundation_privacy";
path = shared_preferences_foundation_privacy.bundle;
remoteRef = 0B21565E2C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B2156612C0D8FFF00D5A718 /* sqflite */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
name = sqflite;
path = sqflite.framework;
remoteRef = 0B2156602C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B2156632C0D8FFF00D5A718 /* sqflite-sqflite_darwin_privacy */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
name = "sqflite-sqflite_darwin_privacy";
path = sqflite_darwin_privacy.bundle;
remoteRef = 0B2156622C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B2156652C0D8FFF00D5A718 /* Toast */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
name = Toast;
path = Toast.framework;
remoteRef = 0B2156642C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B2156672C0D8FFF00D5A718 /* url_launcher_ios */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
name = url_launcher_ios;
path = url_launcher_ios.framework;
remoteRef = 0B2156662C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B2156692C0D8FFF00D5A718 /* url_launcher_ios-url_launcher_ios_privacy */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
name = "url_launcher_ios-url_launcher_ios_privacy";
path = url_launcher_ios_privacy.bundle;
remoteRef = 0B2156682C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B21566B2C0D8FFF00D5A718 /* wakelock */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
name = wakelock;
path = wakelock.framework;
remoteRef = 0B21566A2C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B21566D2C0D8FFF00D5A718 /* webview_flutter_wkwebview */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
name = webview_flutter_wkwebview;
path = webview_flutter_wkwebview.framework;
remoteRef = 0B21566C2C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
0B21566F2C0D8FFF00D5A718 /* webview_flutter_wkwebview-webview_flutter_wkwebview_privacy */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
name = "webview_flutter_wkwebview-webview_flutter_wkwebview_privacy";
path = webview_flutter_wkwebview_privacy.bundle;
remoteRef = 0B21566E2C0D8FFF00D5A718 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
@ -352,7 +757,7 @@
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "";
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 20;
CURRENT_PROJECT_VERSION = 25;
DEVELOPMENT_TEAM = CYDU583KN6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
@ -360,7 +765,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.102;
MARKETING_VERSION = 1.0.108;
PRODUCT_BUNDLE_IDENTIFIER = com.example.markingApp;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@ -490,7 +895,7 @@
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "";
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 20;
CURRENT_PROJECT_VERSION = 25;
DEVELOPMENT_TEAM = CYDU583KN6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
@ -498,7 +903,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.102;
MARKETING_VERSION = 1.0.108;
PRODUCT_BUNDLE_IDENTIFIER = com.example.markingApp;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@ -520,7 +925,7 @@
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "";
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 20;
CURRENT_PROJECT_VERSION = 25;
DEVELOPMENT_TEAM = CYDU583KN6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
@ -528,7 +933,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.102;
MARKETING_VERSION = 1.0.108;
PRODUCT_BUNDLE_IDENTIFIER = com.example.markingApp;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";

View File

@ -33,6 +33,12 @@ mixin CommonMixin {
return RestClientReport(dio, baseUrl: RequestConfig().baseUrlOfReport);
}
// CLIENT
Future<RestClient> getClientLogin() async {
Dio dio = await getDio();
return RestClient(dio, baseUrl: RequestConfig().loginBaseUrl);
}
void setTimeOut(int seconds, call) => Future.delayed(Duration(seconds: seconds), call);
// context

View File

@ -0,0 +1,6 @@
enum ReviewMarksBottomBtnsEnum {
DRAG, //
HANDWRITING, //
RETURN_PREVIOUS_LEVEL, //
CLEAR_ALL //
}

View File

@ -15,8 +15,23 @@ class BottomAnnotationSwitchCleanall extends Object {
BottomAnnotationSwitchCleanall({this.cleanAll = false, this.previousStep = false, this.uploadImage = false});
factory BottomAnnotationSwitchCleanall.fromJson(Map<String, dynamic> srcJson) =>
_$BottomAnnotationSwitchCleanallFromJson(srcJson);
factory BottomAnnotationSwitchCleanall.fromJson(Map<String, dynamic> srcJson) => _$BottomAnnotationSwitchCleanallFromJson(srcJson);
Map<String, dynamic> toJson() => _$BottomAnnotationSwitchCleanallToJson(this);
}
@JsonSerializable()
class BottomAnnotationSwitchCleanallOfMarking extends Object {
@JsonKey(name: 'cleanAll')
bool cleanAll;
@JsonKey(name: 'previousStep')
bool previousStep;
BottomAnnotationSwitchCleanallOfMarking({this.cleanAll = false, this.previousStep = false});
factory BottomAnnotationSwitchCleanallOfMarking.fromJson(Map<String, dynamic> srcJson) =>
_$BottomAnnotationSwitchCleanallOfMarkingFromJson(srcJson);
Map<String, dynamic> toJson() => _$BottomAnnotationSwitchCleanallOfMarkingToJson(this);
}

View File

@ -0,0 +1,12 @@
import 'package:json_annotation/json_annotation.dart';
part 'job_home_refresh_bus.g.dart';
@JsonSerializable()
class JobHomeRefreshBus extends Object {
JobHomeRefreshBus();
factory JobHomeRefreshBus.fromJson(Map<String, dynamic> srcJson) => _$JobHomeRefreshBusFromJson(srcJson);
Map<String, dynamic> toJson() => _$JobHomeRefreshBusToJson(this);
}

View File

@ -1,3 +1,4 @@
import 'package:collection/collection.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:marking_app/common/model/job/job_page_tab.dart';
@ -14,14 +15,21 @@ class JobDoSynchroTab extends Object {
Map<String, dynamic> toJson() => _$JobDoSynchroTabToJson(this);
/// tab下一个tab的pageIndex
int? getNextPageIndex([int? indexLocated]) {
if (indexLocated == null) return null;
return indexLocated == tabs.length - 1 ? null : tabs[indexLocated + 1].pageIndex;
int? getNextPageIndex([int? pageIndex]) {
if (pageIndex == null) return null;
var _index = tabs.indexWhere((e) => e.pageIndex == pageIndex);
if (_index == -1) return null;
return _index == tabs.length - 1 ? null : tabs[_index + 1].pageIndex;
}
/// tab上一个tab的pageIndex
int? getPreviousPageIndex([int? indexLocated]) {
if (indexLocated == null) return null;
return indexLocated == 0 ? null : tabs[indexLocated - 1].pageIndex;
int? getPreviousPageIndex([int? pageIndex]) {
if (pageIndex == null) return null;
var _index = tabs.indexWhere((e) => e.pageIndex == pageIndex);
if (_index == -1) return null;
pageIndex = _index == 0 ? null : tabs[_index - 1].pageIndex;
print('这是上一页的数据:${pageIndex}');
return pageIndex;
}
}

View File

@ -14,11 +14,38 @@ class GestureRecording {
bool scopeBox;
int intervalTime; //
GestureRecording({
required this.eraser,
required this.annotationSwitch,
this.data,
this.usageTime,
this.scopeBox = false,
this.intervalTime = 0,
});
}
/**
* (稿)
*/
class GestureHandwritingRecording {
int stroke;
int usageTime; //
Offset data;
int intervalTime; //
GestureHandwritingRecording({
required this.stroke,
required this.data,
required this.usageTime,
required this.intervalTime,
});
}
/**
* 稿
*/
class ShowStudentMmanuscript {
bool showManuscript; // 稿
ShowStudentMmanuscript(this.showManuscript);
}

View File

@ -0,0 +1,48 @@
import 'package:json_annotation/json_annotation.dart';
part 'job_handwriting.g.dart';
@JsonSerializable()
class JobHandwriting extends Object {
@JsonKey(name: 'lattices')
List<Lattices> lattices;
@JsonKey(name: 'paperPicture')
String paperPicture;
@JsonKey(name: 'pageNum')
int pageNum;
@JsonKey(name: 'pageCount')
int pageCount;
JobHandwriting(this.lattices, this.paperPicture, this.pageNum, this.pageCount);
factory JobHandwriting.fromJson(Map<String, dynamic> srcJson) => _$JobHandwritingFromJson(srcJson);
Map<String, dynamic> toJson() => _$JobHandwritingToJson(this);
}
@JsonSerializable()
class Lattices extends Object {
@JsonKey(name: 'stroke')
int stroke;
@JsonKey(name: 'x')
double x;
@JsonKey(name: 'y')
double y;
@JsonKey(name: 'time')
int time;
@JsonKey(name: 'intervalTime')
int intervalTime;
Lattices(this.stroke, this.x, this.y, this.time, [this.intervalTime = 0]);
factory Lattices.fromJson(Map<String, dynamic> srcJson) => _$LatticesFromJson(srcJson);
Map<String, dynamic> toJson() => _$LatticesToJson(this);
}

View File

@ -0,0 +1,29 @@
import 'package:json_annotation/json_annotation.dart';
part 'job_knowledge_detail_student.g.dart';
@JsonSerializable()
class JobKnowledgeDetailStudent extends Object {
@JsonKey(name: 'studentId')
int studentId;
@JsonKey(name: 'studentName')
String studentName;
@JsonKey(name: 'isAnswer')
bool isAnswer;
@JsonKey(name: 'isCorrect')
bool isCorrect;
JobKnowledgeDetailStudent(this.studentId,this.studentName,this.isAnswer,this.isCorrect,);
factory JobKnowledgeDetailStudent.fromJson(Map<String, dynamic> srcJson) => _$JobKnowledgeDetailStudentFromJson(srcJson);
Map<String, dynamic> toJson() => _$JobKnowledgeDetailStudentToJson(this);
}

View File

@ -0,0 +1,29 @@
import 'package:json_annotation/json_annotation.dart';
part 'job_knowledge_points.g.dart';
@JsonSerializable()
class KnowledgePoints extends Object {
@JsonKey(name: 'knowledgeId')
int knowledgeId;
@JsonKey(name: 'knowledgeName')
String knowledgeName;
@JsonKey(name: 'correctRate')
int correctRate;
@JsonKey(name: 'count')
int count;
KnowledgePoints(this.knowledgeId,this.knowledgeName,this.correctRate,this.count,);
factory KnowledgePoints.fromJson(Map<String, dynamic> srcJson) => _$KnowledgePointsFromJson(srcJson);
Map<String, dynamic> toJson() => _$KnowledgePointsToJson(this);
}

View File

@ -0,0 +1,38 @@
import 'package:json_annotation/json_annotation.dart';
part 'job_knowledge_points_detail.g.dart';
@JsonSerializable()
class KnowledgePointsDetail extends Object {
@JsonKey(name: 'jobId')
int jobId;
@JsonKey(name: 'jobName')
String jobName;
@JsonKey(name: 'publishTime')
String publishTime;
@JsonKey(name: 'questionId')
int questionId;
@JsonKey(name: 'questionNo')
String questionNo;
@JsonKey(name: 'sectionId')
int sectionId;
@JsonKey(name: 'correctRate')
int correctRate;
KnowledgePointsDetail(this.jobId,this.jobName,this.publishTime,this.questionId,this.questionNo,this.sectionId,this.correctRate,);
factory KnowledgePointsDetail.fromJson(Map<String, dynamic> srcJson) => _$KnowledgePointsDetailFromJson(srcJson);
Map<String, dynamic> toJson() => _$KnowledgePointsDetailToJson(this);
}

View File

@ -35,13 +35,17 @@ class TestQuestionsImageInfo extends Object {
double? imageHeightOffsetend;
TestQuestionsImageInfo(
{required this.width,
required this.height,
required this.url,
required this.boxWidth,
required this.boxHeight,
this.pixelRatio = 1}) {
double zoom; //
TestQuestionsImageInfo({
required this.width,
required this.height,
required this.url,
required this.boxWidth,
required this.boxHeight,
this.pixelRatio = 1,
this.zoom = 1,
}) {
// print('图片宽度:$width');
// print('图片高度:$height');
@ -51,11 +55,19 @@ class TestQuestionsImageInfo extends Object {
pixelRatio = width / boxWidth;
scale = boxWidth / width;
scaleHeight = scale! * height;
scaleWidth = scale! * width;
scaleHeight = scale! * height * zoom;
scaleWidth = scale! * width * zoom;
if (scaleHeight != null) {
imageHeightOffsetStart = (boxHeight - scaleHeight!) / 2;
imageHeightOffsetStart = boxHeight <= scaleHeight! ? 0 : (boxHeight - scaleHeight!) / 2;
imageHeightOffsetend = imageHeightOffsetStart! + scaleHeight!;
}
}
//
void calculateStartAndEndHeight([double otherHeight = 0]) {
if (scaleHeight != null) {
imageHeightOffsetStart = (boxHeight - (scaleHeight! + otherHeight)) / 2;
imageHeightOffsetend = imageHeightOffsetStart! + scaleHeight!;
}
}

View File

@ -1,18 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'keyboard_assist_event.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
KeyboardAssistEvent _$KeyboardAssistEventFromJson(Map<String, dynamic> json) =>
KeyboardAssistEvent(
openAuxiliary: json['openAuxiliary'] as bool? ?? false,
);
Map<String, dynamic> _$KeyboardAssistEventToJson(
KeyboardAssistEvent instance) =>
<String, dynamic>{
'openAuxiliary': instance.openAuxiliary,
};

View File

@ -1,27 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'marking_history_zoom_info.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
MarkingHistoryZoomInfo _$MarkingHistoryZoomInfoFromJson(
Map<String, dynamic> json) =>
MarkingHistoryZoomInfo(
markingUserId: json['markingUserId'] as int,
questionNum: json['questionNum'] as String,
scale: (json['scale'] as num).toDouble(),
positionY: (json['positionY'] as num).toDouble(),
positionX: (json['positionX'] as num).toDouble(),
);
Map<String, dynamic> _$MarkingHistoryZoomInfoToJson(
MarkingHistoryZoomInfo instance) =>
<String, dynamic>{
'markingUserId': instance.markingUserId,
'questionNum': instance.questionNum,
'scale': instance.scale,
'positionY': instance.positionY,
'positionX': instance.positionX,
};

View File

@ -15,7 +15,7 @@ part 'marking_list_params.g.dart';
@JsonSerializable()
class MarkingListParams extends BasePage {
@JsonKey(name: 'isFinish')
bool isFinish;
bool? isFinish;
//
@JsonKey(name: 'PageType')
@ -27,7 +27,7 @@ class MarkingListParams extends BasePage {
int? markingType; // 1 2
MarkingListParams({
required this.isFinish,
this.isFinish,
required this.pageType,
required page,
required limit,

View File

@ -96,9 +96,9 @@ class MarkingTextQuestion extends Object {
@JsonKey(name: 'papersUrlStr')
List<String>? papersUrlStr;
//
@JsonKey(name: 'commentImageUrlTodo')
List<String>? commentImageUrlTodo;
// //
// @JsonKey(name: 'commentImageUrlTodo')
// List<String>? commentImageUrlTodo;
// Map
@JsonKey(name: 'commentImageUrlMap')
@ -115,8 +115,8 @@ class MarkingTextQuestion extends Object {
@JsonKey(name: 'historicalScorings')
List<HistoricalScoring>? historicalScorings;
MarkingTextQuestion(this.id, this.totalScore, this.isFinish, this.subQuestionDetailList, this.isException,
this.questionNum, this.score, this.studentAnswerList,
MarkingTextQuestion(
this.id, this.totalScore, this.isFinish, this.subQuestionDetailList, this.isException, this.questionNum, this.score, this.studentAnswerList,
// this.questionIndex,
{required this.commentImageUrl,
required this.lastOne,
@ -130,7 +130,7 @@ class MarkingTextQuestion extends Object {
// this.totalCount = 0,
// this.currentIndex = 0,
this.papersUrl = const [],
this.commentImageUrlTodo,
// this.commentImageUrlTodo,
this.commentImageUrlMap = const {}}) {
score = isFinish ? score : null;
completeRating = isFinish && score != null;
@ -140,14 +140,20 @@ class MarkingTextQuestion extends Object {
commentImageUrlMap = Map();
if (commentImageUrl.isNotEmpty) {
for (var element in commentImageUrl) {
commentImageUrlMap[element] = '$element?${DateTime.now().millisecondsSinceEpoch}';
// for (var element in commentImageUrl) {
// commentImageUrlMap[element] = '$element?${DateTime.now().millisecondsSinceEpoch}';
// }
for (var i = 0; i < commentImageUrl.length; i++) {
var element = commentImageUrl[i];
var originalImage = studentAnswerList[i];
commentImageUrlMap[originalImage] = 'https:$element?${DateTime.now().millisecondsSinceEpoch}';
}
} else {
for (var element in studentAnswerList) {
commentImageUrlMap[element] = element;
}
}
// if (historicalScore != null) {
// this.historicalScorings = (jsonDecode(historicalScore!) as List<dynamic>).map((e) {
// return HistoricalScoring.fromJson(e as Map<String, dynamic>);
@ -165,10 +171,6 @@ class MarkingTextQuestion extends Object {
factory MarkingTextQuestion.fromJson(Map<String, dynamic> srcJson) => _$MarkingTextQuestionFromJson(srcJson);
List<String> getImageData() {
if (commentImageUrlTodo != null && commentImageUrlTodo!.isNotEmpty) {
return commentImageUrlTodo!;
}
if (commentImageUrl.isNotEmpty) {
return commentImageUrl;
}
@ -178,10 +180,10 @@ class MarkingTextQuestion extends Object {
bool setImageList(String resImage, int imageIndex) {
try {
commentImageUrlTodo ??= getImageData().map((e) => e).toList();
String oldImage = studentAnswerList[imageIndex];
commentImageUrlMap[oldImage] = '$resImage?${DateTime.now().millisecondsSinceEpoch}';
commentImageUrlTodo![imageIndex] = resImage;
// commentImageUrlMap[oldImage] = 'https:$resImage?${DateTime.now().millisecondsSinceEpoch}';
commentImageUrlMap[oldImage] = 'https:$resImage?${DateTime.now().millisecondsSinceEpoch}';
return true;
} catch (e) {
return false;
@ -220,11 +222,7 @@ class SubQuestions extends Object {
bool completeRating;
SubQuestions(
{required this.subQuestionScore,
required this.subQuestionNum,
this.subQuestionGotScore,
required this.isFinish,
this.completeRating = false}) {
{required this.subQuestionScore, required this.subQuestionNum, this.subQuestionGotScore, required this.isFinish, this.completeRating = false}) {
subQuestionGotScore = isFinish ? subQuestionGotScore : null;
completeRating = isFinish && subQuestionGotScore != null;
}

View File

@ -0,0 +1,50 @@
import 'package:json_annotation/json_annotation.dart';
part 'report_student_history_record.g.dart';
@JsonSerializable()
class ReportStudentHistoryRecord extends Object {
@JsonKey(name: 'ExamId')
int examId;
@JsonKey(name: 'ExamName')
String examName;
@JsonKey(name: 'ExamStartTime')
String examStartTime;
@JsonKey(name: 'StudentExamNum')
String studentExamNum;
@JsonKey(name: 'ScoreInfo')
List<ScoreInfo> scoreInfo;
ReportStudentHistoryRecord(this.examId,this.examName,this.examStartTime,this.studentExamNum,this.scoreInfo,);
factory ReportStudentHistoryRecord.fromJson(Map<String, dynamic> srcJson) => _$ReportStudentHistoryRecordFromJson(srcJson);
Map<String, dynamic> toJson() => _$ReportStudentHistoryRecordToJson(this);
}
@JsonSerializable()
class ScoreInfo extends Object {
@JsonKey(name: 'Value')
double value;
@JsonKey(name: 'Text')
String text;
ScoreInfo(this.value,this.text,);
factory ScoreInfo.fromJson(Map<String, dynamic> srcJson) => _$ScoreInfoFromJson(srcJson);
Map<String, dynamic> toJson() => _$ScoreInfoToJson(this);
}

View File

@ -0,0 +1,77 @@
import 'package:json_annotation/json_annotation.dart';
part 'report_student_info.g.dart';
@JsonSerializable()
class ReportStudentInfo extends Object {
@JsonKey(name: 'ExamId')
int examId;
@JsonKey(name: 'UserId')
int userId;
@JsonKey(name: 'ClassId')
int classId;
@JsonKey(name: 'ExamName')
String examName;
@JsonKey(name: 'ExamNo')
String examNo;
@JsonKey(name: 'UserName')
String userName;
@JsonKey(name: 'ScoreInfo')
List<ScoreInfo> scoreInfo;
@JsonKey(name: 'Subject')
List<Subject> subject;
ReportStudentInfo(this.examId,this.userId,this.classId,this.examName,this.examNo,this.userName,this.scoreInfo,this.subject,);
factory ReportStudentInfo.fromJson(Map<String, dynamic> srcJson) => _$ReportStudentInfoFromJson(srcJson);
Map<String, dynamic> toJson() => _$ReportStudentInfoToJson(this);
}
@JsonSerializable()
class ScoreInfo extends Object {
@JsonKey(name: 'Value')
double value;
@JsonKey(name: 'Text')
String text;
ScoreInfo(this.value,this.text,);
factory ScoreInfo.fromJson(Map<String, dynamic> srcJson) => _$ScoreInfoFromJson(srcJson);
Map<String, dynamic> toJson() => _$ScoreInfoToJson(this);
}
@JsonSerializable()
class Subject extends Object {
@JsonKey(name: 'Value')
int value;
@JsonKey(name: 'Text')
String text;
Subject(this.value,this.text,);
factory Subject.fromJson(Map<String, dynamic> srcJson) => _$SubjectFromJson(srcJson);
Map<String, dynamic> toJson() => _$SubjectToJson(this);
}

View File

@ -6,14 +6,12 @@
* @FilePath: \marking_app\lib\common\model\UserLogin.dart
* @Description: ,`customMade`, koroFileHeader查看配置 : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import 'package:json_annotation/json_annotation.dart';
import 'package:json_annotation/json_annotation.dart';
part 'user_login.g.dart';
@JsonSerializable(checked: true)
class UserLogin extends Object {
class UserLogin extends Object {
@JsonKey(name: 'access_token')
String accessToken;
@ -23,10 +21,28 @@ part 'user_login.g.dart';
@JsonKey(name: 'token_type')
String tokenType;
UserLogin(this.accessToken,this.expiresIn,this.tokenType,);
UserLogin(
this.accessToken,
this.expiresIn,
this.tokenType,
);
factory UserLogin.fromJson(Map<String, dynamic> srcJson) => _$UserLoginFromJson(srcJson);
Map<String, dynamic> toJson() => _$UserLoginToJson(this);
}
}
@JsonSerializable()
class UseLoginSchool extends Object {
@JsonKey(name: 'schoolId')
int schoolId;
@JsonKey(name: 'schoolName')
String schoolName;
UseLoginSchool(this.schoolId, this.schoolName);
factory UseLoginSchool.fromJson(Map<String, dynamic> srcJson) => _$UseLoginSchoolFromJson(srcJson);
Map<String, dynamic> toJson() => _$UseLoginSchoolToJson(this);
}

View File

@ -6,24 +6,24 @@
* @FilePath: \marking_app\lib\common\model\user\user_login_params.dart
* @Description: ,`customMade`, koroFileHeader查看配置 : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import 'package:json_annotation/json_annotation.dart';
import 'package:json_annotation/json_annotation.dart';
part 'user_login_params.g.dart';
@JsonSerializable()
class UserLoginParams extends Object {
class UserLoginParams extends Object {
@JsonKey(name: 'loginName')
String loginName;
@JsonKey(name: 'password')
String password;
UserLoginParams(this.loginName,this.password,);
@JsonKey(name: 'schoolId')
int? schoolId;
UserLoginParams(this.loginName, this.password, [this.schoolId]);
factory UserLoginParams.fromJson(Map<String, dynamic> srcJson) => _$UserLoginParamsFromJson(srcJson);
Map<String, dynamic> toJson() => _$UserLoginParamsToJson(this);
}
}

View File

@ -22,6 +22,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:marking_app/common/mixin/common.dart';
import 'package:marking_app/common/model/common/base_structure_result.dart';
import 'package:marking_app/common/model/common/upload_img_secret_key.dart';
import 'package:marking_app/common/model/enum/review_marks_bottom_btns_enum.dart';
import 'package:marking_app/common/model/event_bus/bottom_annotation_switch_cleanall.dart';
import 'package:marking_app/common/model/job/test_questions_image_info.dart';
import 'package:marking_app/common/model/job/upload_file_interface_config.dart';
@ -29,10 +30,12 @@ import 'package:marking_app/common/model/job/upload_file_interface_config_params
import 'package:marking_app/common/model/marking/annotation_graffiti_switch.dart';
import 'package:marking_app/common/model/marking/do_marking_keyboard_model.dart';
import 'package:marking_app/common/model/marking/marking_history_zoom_info.dart';
import 'package:marking_app/common/model/marking/marking_text_question.dart';
import 'package:marking_app/common/model/marking/switch_keyboard_to_reload_images.dart';
import 'package:marking_app/pages/common/event_bus_mixin.dart';
import 'package:marking_app/pages/homework_correction/hooks/use_cached_img_refresh.dart';
import 'package:marking_app/pages/marking/hooks/use_zoom_image_history.dart';
import 'package:marking_app/pages/marking/provider/do_paper_bottom_review_marks_provider.dart';
import 'package:marking_app/pages/marking/provider/zoom_height_provider.dart';
import 'package:marking_app/pages/marking/provider/zoom_history_provider.dart';
import 'package:marking_app/provider/annotation_graffiti_switch_provider.dart';
@ -46,7 +49,8 @@ import 'dart:ui' as ui;
import 'package:uuid/uuid.dart';
import 'package:zoom_widget/zoom_widget.dart';
// import 'package:zoom_widget/zoom_widget.dart';
import '../pages/marking/provider/draw_marking_provider.dart';
part 'PictureOverview.g.dart';
typedef PageChanged = void Function(int index);
@ -66,6 +70,8 @@ class PictureOverview extends StatefulHookConsumerWidget {
final bool annotationsFlag;
final String testQuestionNumber;
final Map<String, String> commentImageMap;
final MarkingTextQuestion data;
final Function callAnnotationTips;
const PictureOverview({
required this.imageItems,
@ -74,6 +80,8 @@ class PictureOverview extends StatefulHookConsumerWidget {
required this.testQuestionNumber,
required this.questionNum,
required this.markingUserId,
required this.data,
required this.callAnnotationTips,
this.homework = false,
this.imageScale = 1,
this.imagePosition,
@ -84,7 +92,7 @@ class PictureOverview extends StatefulHookConsumerWidget {
PictureOverviewState createState() => PictureOverviewState();
}
class PictureOverviewState extends ConsumerState<PictureOverview> with CommonMixin {
class PictureOverviewState extends ConsumerState<PictureOverview> with CommonMixin, EventBusMixin {
final GlobalKey theglobalKey = GlobalKey();
final GlobalKey<_ExamPaperDrawingState> examPaperDrawingKey = GlobalKey<_ExamPaperDrawingState>();
final GlobalKey zoomGlobalKey = GlobalKey(); // zoom
@ -100,6 +108,12 @@ class PictureOverviewState extends ConsumerState<PictureOverview> with CommonMix
late RemoveListener _annotationsListener; //
File? temFile; //
//
Offset? globalPosition; //
MarkingHistoryZoomInfo? zoomInfo;
bool illegalArea = false; //
final GlobalKey _zoomKey = GlobalKey<State<Zoom>>();
@override
void initState() {
super.initState();
@ -108,11 +122,12 @@ class PictureOverviewState extends ConsumerState<PictureOverview> with CommonMix
bool flag = value.questionNum == widget.questionNum && value.markingUserId == widget.markingUserId;
if (flag) {
if (value.positionX != 0 && value.positionY != 0) {
zoomOffset = Offset(value.positionX, value.positionY);
// zoomOffset = Offset(value.positionX, value.positionY);
}
if (value.scale < 1) {
initScale = value.scale;
Future.delayed(Duration(seconds: 5), () => ref.read(zoomHistoryProvider.notifier).setState(initScale!));
// 5
Future.delayed(Duration(seconds: 1), () => ref.read(zoomHistoryProvider.notifier).setState(initScale!));
}
}
});
@ -123,19 +138,49 @@ class PictureOverviewState extends ConsumerState<PictureOverview> with CommonMix
graffitiSwitch = state;
toUpState(setState, () {}, mounted);
});
// 线
eventOn(callback: (BottomAnnotationSwitchCleanallOfMarking item) async {
widget.callAnnotationTips(); //
if (ref.read(drawMarkingProvider).data.isEmpty) {
if (widget.data.commentImageUrl.isNotEmpty) {
bool? res = await showDialog<bool>(
//
barrierDismissible: false,
context: context,
builder: (context1) {
return AlertDialog(content: quickText("是否撤销上次批阅批注痕迹"), actions: <Widget>[
TextButton(child: quickText("取消"), onPressed: () => Navigator.pop(context1, false)),
TextButton(child: quickText("确定", color: Theme.of(context).primaryColor), onPressed: () => Navigator.pop(context1, true))
]);
},
);
if (res == true) {
widget.data.commentImageUrl.removeAt(currentIndex);
var theUrl = widget.imageItems[currentIndex];
widget.commentImageMap[theUrl] = theUrl;
toUpState(setState, () {}, mounted);
}
} else {
ToastUtils.showInfo('批注已清空');
}
}
});
}
@override
void dispose() {
super.dispose();
_annotationsListener();
eventCancel();
try {
_imageStream?.removeListener(_imageStreamListener!);
if (temFile != null) {
bool flieExist = temFile!.existsSync();
if (flieExist) temFile!.delete();
}
// if (zoomOffset != null) saveZoomPosition();
} catch (e) {}
super.dispose();
}
Future<FileResult?> saveImage() async {
@ -146,9 +191,12 @@ class PictureOverviewState extends ConsumerState<PictureOverview> with CommonMix
//
RenderRepaintBoundary? boundary = theglobalKey.currentContext!.findRenderObject() as RenderRepaintBoundary?;
if (boundary == null) return null;
double dpr = MediaQuery.of(context).devicePixelRatio;
// double dpr = ui.window.devicePixelRatio;
ui.Image image = await boundary.toImage(pixelRatio: dpr);
// double dpr = MediaQuery.of(context).devicePixelRatio;
double pixelRatio = MediaQuery.of(context).devicePixelRatio;
if (imagInfoModel?.pixelRatio != null) pixelRatio = imagInfoModel!.pixelRatio;
ui.Image image = await boundary.toImage(pixelRatio: pixelRatio);
ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);
if (byteData == null) {
/// null
@ -162,11 +210,14 @@ class PictureOverviewState extends ConsumerState<PictureOverview> with CommonMix
temFile = file;
}
crypto.Digest fileMd5 = crypto.md5.convert(await temFile!.readAsBytes());
if (imagInfoModel != null) {
//
}
crypto.Digest fileMd5 = crypto.md5.convert(await temFile!.readAsBytes());
RestClient _client = await getClient();
BaseStructureResult<UploadFileInterfaceConfig> resUploadConfig =
await _client.getUploadFile(UploadFileInterfaceConfigParams(
BaseStructureResult<UploadFileInterfaceConfig> resUploadConfig = await _client.getMarkingUploadFile(UploadFileInterfaceConfigParams(
fileName: '1.png',
fileMd5: fileMd5.toString(),
contentLength: temFile!.lengthSync(),
@ -179,8 +230,7 @@ class PictureOverviewState extends ConsumerState<PictureOverview> with CommonMix
if (resUploadConfig.data!.uploadUri == null) {
return FileResult(myObject: '', success: true, url: resUploadConfig.data!.downloadUri);
}
FileResult? resFile =
await ref.read(uploadFileProvider.notifier).getUploadFileConfig(resUploadConfig.data!, temFile!);
FileResult? resFile = await ref.read(uploadFileProvider.notifier).getUploadFileConfig(resUploadConfig.data!, temFile!);
// FileResult? resFile = await ref
// .read(uploadFileProvider.notifier)
// .uploadFile(temFile!.path, widget.imageItems[currentIndex], ref.read(userProvider).id.toString());
@ -210,27 +260,60 @@ class PictureOverviewState extends ConsumerState<PictureOverview> with CommonMix
FastData.getInstance().setMarkingZoomInfo(info);
}
void saveZoomPosition() async {
MarkingHistoryZoomInfo? historyZoomInfo = await FastData.getInstance().getMarkingZoomInfo();
if (historyZoomInfo != null) {
FastData.getInstance().setMarkingZoomInfo(MarkingHistoryZoomInfo(
scale: historyZoomInfo.scale,
positionX: zoomOffset!.dx,
positionY: zoomOffset!.dy,
questionNum: historyZoomInfo.questionNum,
markingUserId: historyZoomInfo.markingUserId,
));
}
}
void onPanUpPosition(Offset val) async {
//
// print('**************** 正在移动位置 YYY:${val.dy}');
// print('**************** 正在移动位置 XXX:${val.dx}');
zoomOffset = val;
}
// ==>
void onScaleUpdate(double scale, double scale1) async {
print('这是第一个scale$scale');
print('这是第二个noScale$scale1');
void onScaleUpdate(double scale, double zoom) async {
// print('zoom$zoom');
// print('scale${scale}');
// MarkingHistoryZoomInfo? historyZoomInfo = await FastData.getInstance().getMarkingZoomInfo();
MarkingHistoryZoomInfo? historyZoomInfo = await FastData.getInstance().getMarkingZoomInfo();
double positionX = historyZoomInfo?.positionX ?? 0;
double positionY = historyZoomInfo?.positionY ?? 0;
MarkingHistoryZoomInfo info = MarkingHistoryZoomInfo(
scale: scale1,
scale: zoom,
positionX: positionX,
positionY: positionY,
questionNum: widget.questionNum,
markingUserId: widget.markingUserId,
);
zoomInfo = info;
// if (double.parse(zoom.toStringAsFixed(2)) <= 1) zoom = 1;
if (imagInfoModel != null) {
//
imagInfoModel = TestQuestionsImageInfo(
//
boxHeight: imagInfoModel!.boxHeight,
boxWidth: imagInfoModel!.boxWidth,
url: imagInfoModel!.url,
height: imagInfoModel!.height,
width: imagInfoModel!.width,
zoom: zoom,
);
}
FastData.getInstance().setMarkingZoomInfo(info);
}
@override
Widget build(BuildContext context) {
DoMarkingKeyboardModel _model = ref.watch(markingKeyboardProvider);
return Container(
width: double.infinity,
height: double.infinity,
@ -257,10 +340,9 @@ class PictureOverviewState extends ConsumerState<PictureOverview> with CommonMix
temFile = file;
print('更新需要上传的文件');
},
imageBuilder: (context, imageProvider) {
imageBuilder: (imageBuilderContext, imageProvider) {
Image imageWidget = Image(image: imageProvider, fit: BoxFit.fitWidth);
if (imagInfoModel == null ||
(imagInfoModel?.boxHeight != containerHeight || imagInfoModel?.boxWidth != containerWidth)) {
if (imagInfoModel == null || (imagInfoModel?.boxHeight != containerHeight || imagInfoModel?.boxWidth != containerWidth)) {
if (_imageStreamListener != null) _imageStream?.removeListener(_imageStreamListener!);
_imageStreamListener = ImageStreamListener((ImageInfo info, bool _) {
imagInfoModel = TestQuestionsImageInfo(
@ -271,7 +353,6 @@ class PictureOverviewState extends ConsumerState<PictureOverview> with CommonMix
height: info.image.height.toDouble(),
width: info.image.width.toDouble(),
);
printJson(imagInfoModel!.toJson());
Future.delayed(Duration.zero, () {
ref.read(zoomHeightProvider.notifier).setState(imagInfoModel?.scaleHeight ?? 0.0);
});
@ -279,20 +360,111 @@ class PictureOverviewState extends ConsumerState<PictureOverview> with CommonMix
_imageStream = imageWidget.image.resolve(ImageConfiguration())..addListener(_imageStreamListener!);
}
var btnEnum = ref.watch(doPaperBottomReviewMarksProvider);
// return imageWidget;
return Zoom(
// initTotalZoomOut: true,
child: imageWidget,
maxZoomWidth: containerWidth,
canvasColor: Colors.transparent,
backgroundColor: Colors.transparent,
maxZoomHeight: imagInfoModel?.scaleHeight,
initScale: initScale ?? 1,
initPosition: zoomOffset,
// initPosition: ,
// onPositionUpdate: onPositionUpdate,
onScaleUpdate: onScaleUpdate,
// zoomSensibility: 0.5,
return Listener(
behavior: HitTestBehavior.opaque,
onPointerMove: (PointerMoveEvent details) {
if (btnEnum != ReviewMarksBottomBtnsEnum.HANDWRITING) return;
if (globalPosition != null) {
//
double dx = globalPosition!.dx;
double dy = globalPosition!.dy;
double dxNew = details.localPosition.dx;
double dyNew = details.localPosition.dy;
if ((dxNew - dx).abs() > 22 || (dyNew - dy).abs() > 22) return;
}
globalPosition = details.localPosition;
Offset localPosition = globalPosition!;
// if (imagInfoModel != null &&
// (localPosition.dy < imagInfoModel!.imageHeightOffsetStart! || localPosition.dy > imagInfoModel!.imageHeightOffsetend!)) {
// //
// var dataVal = ref.read(drawMarkingProvider).data;
// if (dataVal.length - 1 > -1 && dataVal[dataVal.length - 1].data != null) {
// var newVal = ref.read(drawMarkingProvider).data..add(GestureRecording(eraser: graffitiSwitch.openEraser));
// var newVal1 = ref.read(drawMarkingProvider).offsets..add(null);
// ref.read(drawMarkingProvider.notifier).setState(DrawMarkingVal(newVal, newVal1));
// }
// illegalArea = true;
// return;
// }
// illegalArea = false;
var _theKey = _zoomKey.currentState;
print(_theKey);
double remainingHeight = imagInfoModel!.imageHeightOffsetStart!; //
if (remainingHeight > 1) {
localPosition = Offset(localPosition.dx, localPosition.dy - remainingHeight);
}
// print(localPosition.dy);
print(localPosition.dx);
double _theZoomVal = imagInfoModel?.zoom ?? 1;
var _dx = zoomOffset?.dx ?? 0;
_dx = _dx > 0 ? 0 : _dx.abs() / _theZoomVal;
var _dy = zoomOffset?.dy ?? 0;
_dy = _dy > 0 ? 0 : _dy.abs() / _theZoomVal;
if (_theZoomVal > 1) {
//
localPosition = Offset(localPosition.dx / _theZoomVal, localPosition.dy / _theZoomVal);
if (zoomOffset != null) {
//
localPosition = Offset(localPosition.dx + _dx, localPosition.dy + _dy);
}
} else if (_theZoomVal < 1) {
//
double imgSpaceWidthOfSingle = (imagInfoModel!.boxWidth - imagInfoModel!.scaleWidth!) / 2;
localPosition = Offset((localPosition.dx - imgSpaceWidthOfSingle) / _theZoomVal, localPosition.dy / _theZoomVal + _dy);
// localPosition = Offset(localPosition.dx * _theZoomVal - imgSpaceWidthOfSingle, localPosition.dy / _theZoomVal);
} else {
localPosition = Offset(localPosition.dx, localPosition.dy + _dy);
}
var newVal = ref.read(drawMarkingProvider).data..add(GestureRecording(eraser: graffitiSwitch.openEraser, data: localPosition));
var newVal1 = ref.read(drawMarkingProvider).offsets..add(localPosition);
ref.read(drawMarkingProvider.notifier).setState(DrawMarkingVal(newVal, newVal1));
widget.callAnnotationTips();
},
// onPointerDown: (PointerDownEvent event) {
// },
onPointerUp: (PointerUpEvent details) {
if (btnEnum != ReviewMarksBottomBtnsEnum.HANDWRITING) return;
//
if (illegalArea) return;
globalPosition = null;
var newVal = ref.read(drawMarkingProvider).data..add(GestureRecording(eraser: graffitiSwitch.openEraser));
var newVal1 = ref.read(drawMarkingProvider).offsets..add(null);
ref.read(drawMarkingProvider.notifier).setState(DrawMarkingVal(newVal, newVal1));
},
child: IgnorePointer(
ignoring: btnEnum != ReviewMarksBottomBtnsEnum.DRAG,
child: Zoom(
key: _zoomKey,
// initTotalZoomOut: true,
child: ExamPaperDrawing(
key: examPaperDrawingKey,
globalKey: theglobalKey,
child: imageWidget,
graffitiSwitch: graffitiSwitch,
decoration: const BoxDecoration(color: const Color.fromRGBO(249, 250, 254, 1)),
),
maxZoomWidth: containerWidth,
canvasColor: Colors.transparent,
backgroundColor: Colors.transparent,
maxZoomHeight: imagInfoModel?.scaleHeight != null ? (imagInfoModel!.scaleHeight! / imagInfoModel!.zoom) : null,
initScale: initScale ?? 1,
initPosition: zoomOffset,
onScaleUpdate: onScaleUpdate,
onPositionUpdate: onPanUpPosition,
),
),
);
},
);
@ -303,24 +475,17 @@ class PictureOverviewState extends ConsumerState<PictureOverview> with CommonMix
//
class ExamPaperDrawing extends StatefulHookConsumerWidget {
String imgUrl;
bool homework;
// String imgUrl;
Widget child;
BoxDecoration? decoration;
AnnotationGraffitiSwitch graffitiSwitch;
List<GestureRecording>? points;
List<dynamic>? pointsPureData;
ValueNotifier<Map<String, ui.Image>> imageLoaded;
GlobalKey globalKey;
// Function(String) imageCall;
ExamPaperDrawing({
required this.imgUrl,
required this.homework,
required this.points,
required this.pointsPureData,
// required this.imgUrl,
required this.child,
required this.graffitiSwitch,
required this.globalKey,
required this.imageLoaded,
this.decoration,
Key? key,
}) : super(key: key);
@ -329,73 +494,37 @@ class ExamPaperDrawing extends StatefulHookConsumerWidget {
_ExamPaperDrawingState createState() => _ExamPaperDrawingState();
}
class _ExamPaperDrawingState extends ConsumerState<ExamPaperDrawing>
with EventBusMixin<BottomAnnotationSwitchCleanall> {
late Future<ui.Image?> _future; //
class _ExamPaperDrawingState extends ConsumerState<ExamPaperDrawing> with EventBusMixin<BottomAnnotationSwitchCleanallOfMarking> {
//
late List<GestureRecording> points;
late List<dynamic> pointsPureData;
//
bool _isEraserPressed = false; //
Offset? _eraserPosition; //
Offset? globalPosition = null; //
Future<ui.Image?> loadImage(String url) async {
try {
Map<String, ui.Image> map = widget.imageLoaded.value;
ui.Image? image = map[url];
if (image != null) {
return image;
}
final httpClient = HttpClient();
final request = await httpClient.getUrl(Uri.parse(url));
final response = await request.close();
final bytes = await consolidateHttpClientResponseBytes(response);
final codec = await ui.instantiateImageCodec(bytes);
final frame = await codec.getNextFrame();
ui.Image theImage = frame.image;
map[url] = theImage;
return theImage;
} catch (e) {
print('请求图片报错:${e.toString()}');
}
return null;
}
// void _onPointerDown(DragDownDetails details) {
// if (widget.graffitiSwitch.openEraser) {
// _eraserPosition = (context.findRenderObject() as RenderBox).globalToLocal(details.globalPosition);
// _isEraserPressed = true;
// toUpState(setState, ()=>{}, mounted);
// }
// }
late RemoveListener removeListener;
late ValueNotifier<List<GestureRecording>> _vnHandWritings;
late List<Offset?> pointsPureData = [];
@override
void initState() {
points = widget.points ?? [];
pointsPureData = widget.pointsPureData ?? [];
print('图片地址:${widget.imgUrl}');
_future = loadImage(widget.imgUrl);
_vnHandWritings = ValueNotifier<List<GestureRecording>>([]);
removeListener = ref.read(drawMarkingProvider.notifier).addListener((state) {
pointsPureData = state.offsets;
_vnHandWritings.value = [...state.data];
}, fireImmediately: false);
// 线
eventOn(callback: (BottomAnnotationSwitchCleanall item) {
eventOn(callback: (BottomAnnotationSwitchCleanallOfMarking item) {
if (item.previousStep) {
if (points.isEmpty) {
ToastUtils.showInfo('批注已清空');
if (ref.read(drawMarkingProvider).data.isEmpty) {
return;
}
var index = pointsPureData.toList().lastIndexOf(null);
if (index != -1) {
if (index + 1 == pointsPureData.length) {
pointsPureData = pointsPureData.sublist(0, index);
points.sublist(0, index);
index = pointsPureData.toList().lastIndexOf(null);
index == -1 ? -1 : index + 1;
index = index == -1 ? -1 : index + 1;
}
if (index != -1) {
pointsPureData = pointsPureData.sublist(0, index);
points = points.sublist(0, index);
toUpState(setState, () {}, mounted);
ref.read(drawMarkingProvider.notifier).setState(DrawMarkingVal(ref.read(drawMarkingProvider).data.sublist(0, index), pointsPureData));
} else {
item.cleanAll = true;
}
@ -406,21 +535,7 @@ class _ExamPaperDrawingState extends ConsumerState<ExamPaperDrawing>
if (item.cleanAll) {
pointsPureData.clear();
points.clear();
toUpState(setState, () {}, mounted);
}
if (item.uploadImage) {
//
if (pointsPureData.isEmpty) {
ToastUtils.showInfo('请先批注再提交');
return;
}
// _saveImage().then((FileResult? res) {
// if (res != null) {
// widget.imageCall(res.url!);
// }
// });
ref.read(drawMarkingProvider.notifier).setState(DrawMarkingVal([], []));
}
});
super.initState();
@ -428,196 +543,65 @@ class _ExamPaperDrawingState extends ConsumerState<ExamPaperDrawing>
@override
void dispose() {
super.dispose();
eventCancel();
removeListener();
_vnHandWritings.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MyFutureBuilder.buildFutureBuilderOfSingleInstance<ui.Image>(
context,
_future,
(ui.Image? theImage) {
if (theImage == null) return const Center(child: Text('图片加载错误'));
print('_ExamPaperDrawingState的build....');
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
final double containerWidth = constraints.maxWidth; //
final double containerHeight = constraints.maxHeight; //
final double imageWidth = theImage.width.toDouble(); //
final double imageHeight = theImage.height.toDouble(); //
final double widthRatio = containerWidth / imageWidth; //
final double heightRatio = containerHeight / imageHeight;
final double scale = widthRatio > heightRatio ? heightRatio : widthRatio;
final double destWidth = imageWidth * scale;
final double destHeight = imageHeight * scale;
final bool homework = widget.homework;
return GestureDetector(
behavior: HitTestBehavior.opaque,
onPanUpdate: (DragUpdateDetails details) {
if (globalPosition != null) {
//
double dx = globalPosition!.dx;
double dy = globalPosition!.dy;
double dxNew = details.globalPosition.dx;
double dyNew = details.globalPosition.dy;
if ((dxNew - dx).abs() > 22 || (dyNew - dy).abs() > 22) {
return;
}
}
globalPosition = details.globalPosition;
try {
if (widget.graffitiSwitch.openBrush || widget.graffitiSwitch.openEraser) {
RenderBox renderBox = context.findRenderObject() as RenderBox;
Offset localPosition = renderBox.globalToLocal(details.globalPosition);
pointsPureData = List.from(pointsPureData)..add(localPosition);
points = List.from(points)
..add(GestureRecording(eraser: widget.graffitiSwitch.openEraser, data: localPosition));
_eraserPosition = localPosition;
_isEraserPressed = true;
setState(() {});
}
} catch (e) {
toPrint(val: '进入报错');
}
},
onPanEnd: (DragEndDetails details) {
print('离开.............');
globalPosition = null;
if (widget.graffitiSwitch.openBrush || widget.graffitiSwitch.openEraser) {
pointsPureData.add(null); // 线
points.add(GestureRecording(eraser: widget.graffitiSwitch.openEraser));
_isEraserPressed = false;
_eraserPosition = null;
}
},
child: RepaintBoundary(
key: widget.globalKey,
child: CustomPaint(
// isComplex: true,
// willChange: true,
painter: DrawingPainter(
image: theImage,
points: points,
isErasing: widget.graffitiSwitch.openEraser,
destWidth: destWidth,
destHeight: destHeight,
imageWidth: imageWidth,
imageHeight: imageHeight,
homework: homework,
containerWidth: containerWidth,
containerHeight: containerHeight,
),
// size: Size(homework ? containerWidth : destWidth, homework ? containerHeight : destHeight),
size: Size(containerWidth, containerHeight),
),
),
);
},
);
},
return RepaintBoundary(
key: widget.globalKey,
child: CustomPaint(
isComplex: true,
willChange: true,
foregroundPainter: DrawingPainter(ctrl: _vnHandWritings),
child: widget.child,
),
);
}
}
class DrawingPainter extends CustomPainter {
final List<GestureRecording> points;
final bool isErasing;
final ui.Image image;
final bool homework;
final double containerWidth;
final double containerHeight;
double destWidth;
double destHeight;
final double imageWidth;
final double imageHeight;
// final Rect destRect;
// final Rect srcRect;
final bool openErasing;
DrawingPainter({
required this.homework,
required this.points,
required this.isErasing,
required this.image,
required this.destWidth,
required this.destHeight,
required this.containerWidth,
required this.containerHeight,
required this.imageWidth,
required this.imageHeight,
}) :
// destRect = Rect.fromLTWH(0, 0,destWidth,destHeight),
// srcRect = Rect.fromLTWH(0, 0, imageWidth, imageHeight),
openErasing = points.isNotEmpty && isErasing,
super();
Paint paintBrush = Paint()
..color = Colors.red
..strokeCap = StrokeCap.round
..strokeWidth = 1.5;
Paint eraser = Paint()
..blendMode = BlendMode.clear
..color = Colors.transparent
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round
..strokeWidth = 100;
final emptyPaint = Paint();
final emptyPaintWithWidth = Paint()..strokeWidth = 60.0;
final ValueNotifier<List<GestureRecording>> ctrl;
final Paint paintBrush = Paint();
DrawingPainter({required this.ctrl}) : super(repaint: ctrl) {
paintBrush
..color = Colors.red
..strokeCap = StrokeCap.round
..strokeWidth = 1.5.r;
}
@override
void paint(Canvas canvas, Size size) {
double offsetX = (size.width - destWidth) / 2;
double offsetY = (size.height - destHeight) / 2;
if (destWidth < (size.width / 2)) {
destWidth = size.width / 2;
offsetX = (size.width - destWidth) / 2;
}
// final rect = Rect.fromCenter(center: center, width: destWidth, height: destHeight);
Rect srcRect = Rect.fromLTRB(0, 0, image.width.toDouble(), image.height.toDouble());
// Rect destRect = Rect.fromLTRB(offsetX, offsetY, containerWidth, containerHeight);
Rect destRect = Offset(offsetX, offsetY) & Size(destWidth, destHeight);
canvas.drawImageRect(image, srcRect, destRect, emptyPaint);
// canvas.drawImage(image, Offset.zero, emptyPaint);
if (points.isNotEmpty) {
// canvas.saveLayer(destRect, emptyPaintWithWidth); //
canvas.saveLayer(Rect.largest, emptyPaintWithWidth); //
canvas.drawColor(Colors.transparent, BlendMode.clear);
}
for (int i = 0; i < points.length - 1; i++) {
var points = ctrl.value;
var pointsLength = points.length;
print('数据.....................[[[[[${points.length}]]]]]');
for (int i = 0; i < pointsLength; i++) {
GestureRecording item = points[i];
GestureRecording nextItem = points[i + 1];
Offset? offsetData = item.data;
Offset? nextOffsetData = nextItem.data;
Offset? nextOffsetData = pointsLength - 1 == i ? null : points[i + 1].data;
if (offsetData != null && nextOffsetData != null) {
canvas.drawLine(offsetData, nextOffsetData, !item.eraser ? paintBrush : eraser);
canvas.drawLine(offsetData, nextOffsetData, paintBrush);
}
}
// .
if (points.isNotEmpty) canvas.restore();
}
// @override
// bool shouldRepaint(DrawingPainter oldDelegate) {
// List<GestureRecording> thePoints = oldDelegate.points;
// // var flag = oldDelegate.points != points || oldDelegate.isErasing != isErasing;
// return thePoints != points;
// }
@override
bool shouldRepaint(DrawingPainter oldDelegate) => true;
bool shouldRepaint(covariant CustomPainter oldDelegate) {
print('FFFFFF55555555555555');
// if (oldDelegate is DrawingPainter) {
// var repaint = ctrl.value.length != oldDelegate.ctrl.value.length || oldDelegate.ctrl.value != ctrl.value;
// print('调用是否绘制:$repaint');
// return repaint;
// }
return false;
}
}
/**
@ -676,51 +660,6 @@ Widget $myCachedNetworkImage({
);
},
);
// return Container(
// width: width,
// height: height,
// color: Colors.red,
// alignment: Alignment.center,
// child: tempFile != null
// ? Image.file(
// tempFile,
// fit: BoxFit.contain,
// width: double.infinity,
// height: double.infinity,
// )
// : CachedNetworkImage(
// key: _useImgRefsh.imageKey.value,
// fit: BoxFit.contain,
// width: double.infinity,
// // height: double.infinity,
// imageUrl: imageUrl,
// placeholder: (context, url) =>
// Center(child: SpinKitWave(color: Theme.of(context).primaryColor, size: 50.r)),
// // imageBuilder: (context, imageProvider) => Container(
// // decoration: BoxDecoration(
// // image: DecorationImage(
// // image: imageProvider,
// // fit: BoxFit.fitWidth,
// // // colorFilter: ColorFilter.mode(Colors.red, BlendMode.colorBurn),
// // ),
// // ),
// // ),
// errorWidget: (context, url, error) {
// return GestureDetector(
// onTap: () => (_useImgRefsh.imageKey.value = UniqueKey()),
// child: Column(
// mainAxisSize: MainAxisSize.min,
// crossAxisAlignment: CrossAxisAlignment.center,
// children: [
// Image.asset('assets/images/test_paper_loading_failed.png'),
// quickText('加载失败,点击重试', color: Color.fromRGBO(148, 163, 182, 1), size: 12.sp),
// ],
// ),
// );
// },
// ),
// );
}
class CacheNetImageView extends ConsumerWidget {
@ -802,9 +741,7 @@ Widget $localAndNetworkSwitch(
useValueChanged<bool, String>(drawFlag, (oldValue, oldResult) {
if (!drawFlag) {
//
_useSwitch
.createTempFile(context, theglobalKey: theglobalKey, examGlobalKey: examGlobalKey)
.then((File? theFile) {
_useSwitch.createTempFile(context, theglobalKey: theglobalKey, examGlobalKey: examGlobalKey).then((File? theFile) {
if (theFile == null) {
// TODO
// _useSwich.showZoomImg.value true还是展示的原来的绘图组件ExamPaperDrawing
@ -832,50 +769,13 @@ Widget $localAndNetworkSwitch(
}, []);
print('是否更新视图.... ${_useZoomHistory.initPosition.value}');
return _useSwitch.showZoomImg.value
?
/**
Scrollbar(
// thumbVisibility: true,
thumbVisibility: true,
controller: _useScrollController,
child: SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
padding: EdgeInsets.zero,
scrollDirection: Axis.vertical, //
child: Transform.scale(
scale: 0.4,
alignment: Alignment.topCenter,
child: $MyCachedNetworkImage(
imageUrl: imageUrl,
tempFile: _useSwitch.temFile.value,
width: containerWidth,
height: containerHeight,
),
),
),
)*/
/** */
$MyCachedNetworkImage(
imageUrl: imageUrl,
tempFile: _useSwitch.temFile.value,
width: containerWidth,
height: containerHeight,
imageBuilder: imageBuilder,
)
: ExamPaperDrawing(
imgUrl: imageUrl,
graffitiSwitch: graffitiSwitch,
points: _useSwitch.points.value,
pointsPureData: _useSwitch.pointsPureData.value,
decoration: const BoxDecoration(color: const Color.fromRGBO(249, 250, 254, 1)),
globalKey: theglobalKey,
key: examGlobalKey,
imageLoaded: _useSwitch.imageLoaded,
homework: homework,
// imageCall: (String str) => widget.imageCall(str, currentIndex),
);
return $MyCachedNetworkImage(
imageUrl: imageUrl,
tempFile: _useSwitch.temFile.value,
width: containerWidth,
height: containerHeight,
imageBuilder: imageBuilder,
);
}
class UseLocalAndNetworkSwitch {
@ -938,7 +838,7 @@ class UseLocalAndNetworkSwitch {
temFile.value?.delete();
temFile.value = file; //
points.value = examGlobalKey.currentState?.points;
points.value = examGlobalKey.currentState?._vnHandWritings.value;
pointsPureData.value = examGlobalKey.currentState?.pointsPureData;
toPrint(val: '图片保存成功:');
return temFile.value;

View File

@ -29,9 +29,7 @@ class TestPaperItem extends ConsumerWidget with CommonMixin {
final bool isHomeworkCorrection;
final VoidCallback? call;
final MarkingListType? markingtype;
const TestPaperItem(
{required this.markingItem, this.markingtype, this.isHomeworkCorrection = false, this.call, Key? key})
: super(key: key);
const TestPaperItem({required this.markingItem, this.markingtype, this.isHomeworkCorrection = false, this.call, Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
@ -65,7 +63,7 @@ class TestPaperItem extends ConsumerWidget with CommonMixin {
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 10.h),
constraints: BoxConstraints(
minHeight: 120.h,
maxHeight: 130.h,
maxHeight: 144.h,
),
decoration: BoxDecoration(
color: Colors.white,
@ -117,8 +115,7 @@ class TestPaperItem extends ConsumerWidget with CommonMixin {
margin: EdgeInsets.only(right: 8.w),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius:
BorderRadius.only(topLeft: Radius.circular(6.r), bottomRight: Radius.circular(6.r)),
borderRadius: BorderRadius.only(topLeft: Radius.circular(6.r), bottomRight: Radius.circular(6.r)),
color: const Color.fromRGBO(245, 108, 108, 0.236),
),
child: Text(
@ -137,8 +134,7 @@ class TestPaperItem extends ConsumerWidget with CommonMixin {
margin: EdgeInsets.only(right: 8.w),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius:
BorderRadius.only(topLeft: Radius.circular(6.r), bottomRight: Radius.circular(6.r)),
borderRadius: BorderRadius.only(topLeft: Radius.circular(6.r), bottomRight: Radius.circular(6.r)),
color: const Color.fromRGBO(4, 201, 208, 0.10),
),
child: Text(
@ -157,8 +153,7 @@ class TestPaperItem extends ConsumerWidget with CommonMixin {
margin: EdgeInsets.only(right: 8.w),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius:
BorderRadius.only(topLeft: Radius.circular(6.r), bottomRight: Radius.circular(6.r)),
borderRadius: BorderRadius.only(topLeft: Radius.circular(6.r), bottomRight: Radius.circular(6.r)),
color: const Color.fromRGBO(231, 236, 255, 1),
),
child: Text(
@ -270,10 +265,7 @@ class TestPaperItem extends ConsumerWidget with CommonMixin {
Text(
'${markingItem.finishCount}',
style: TextStyle(
color: markingItem.isFinish && isHomeworkCorrection
? Colors.green
: Theme.of(context).primaryColor,
fontSize: 12.sp),
color: markingItem.isFinish && isHomeworkCorrection ? Colors.green : Theme.of(context).primaryColor, fontSize: 12.sp),
),
Text(
'/',
@ -299,8 +291,7 @@ class TestPaperItem extends ConsumerWidget with CommonMixin {
style: TextStyle(color: Colors.white, fontSize: 8.sp),
),
// linearStrokeCap: LinearStrokeCap.butt,
progressColor:
markingItem.isFinish && isHomeworkCorrection ? Colors.green : Theme.of(context).primaryColor,
progressColor: markingItem.isFinish && isHomeworkCorrection ? Colors.green : Theme.of(context).primaryColor,
backgroundColor: const Color.fromRGBO(219, 224, 243, 1),
barRadius: Radius.circular(10.r),
),
@ -503,9 +494,7 @@ class TestPaperItem extends ConsumerWidget with CommonMixin {
RestClient client = await getClient();
BaseStructureResult<bool?> result = await client.endMarkingTask(markingUserId);
if (result.code == RequestConfig.successCode && result.data == null ? false : result.data!) {
ref
.read(currentTaskIdProvider.notifier)
.setDoTaskEntity(CurrentReviewTask(taskId: markingItem.markingUserId, refresh: true));
ref.read(currentTaskIdProvider.notifier).setDoTaskEntity(CurrentReviewTask(taskId: markingItem.markingUserId, refresh: true));
} else {
ToastUtils.getFluttertoast(context: context, msg: '提交失败');
}

View File

@ -1,298 +0,0 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:marking_app/common/model/enum/KeyboardType.dart';
import 'package:marking_app/common/model/event_bus/bottom_annotation_switch_cleanall.dart';
import 'package:marking_app/common/model/marking/annotation_graffiti_switch.dart';
import 'package:marking_app/common/model/marking/do_marking_keyboard_model.dart';
import 'package:marking_app/pages/common/event_bus_mixin.dart';
import 'package:marking_app/provider/annotation_graffiti_switch_provider.dart';
import 'package:marking_app/provider/do_marking_provider.dart';
import 'package:marking_app/utils/index.dart';
/**
*
*/
class BottomAnnotationSwitch extends StatefulHookConsumerWidget {
final double? maxWidth;
final bool homework;
const BottomAnnotationSwitch({this.maxWidth, this.homework = false, Key? key}) : super(key: key);
@override
_BottomAnnotationSwitchState createState() => _BottomAnnotationSwitchState();
}
class _BottomAnnotationSwitchState extends ConsumerState<BottomAnnotationSwitch>
with SingleTickerProviderStateMixin, EventBusMixin<BottomAnnotationSwitchCleanall> {
late RemoveListener _annotationsListener; //
late AnimationController _animationController; //
late AnnotationGraffitiSwitch graffitiSwitch;
late DoMarkingKeyboardModel _preferenceModel;
late double upperBound;
late double lowerBound;
Color? bgc;
bool isIos = false;
@override
void initState() {
if (Platform.isIOS) {
toPrint(val: 'IOS');
isIos = true;
} else if (Platform.isAndroid) {
toPrint(val: '安卓');
}
var graffitiHander = ref.read(annotationGraffitiSwitchProvider.notifier);
if (widget.homework) {
setTimeOut(500, () {
graffitiHander.setSwitch(true);
if (!graffitiHander.state.openBrush) graffitiHander.setSwitchBrush();
}); //
}
_preferenceModel = ref.read(markingKeyboardProvider.notifier).state; //
bool isVertical = _preferenceModel.screenDirection == ScreenDirection.VERTICAL_SCREEN; //
switch (_preferenceModel.keyboard) {
case KeyboardType.RIGHT_SELECTION:
double isVerticalNumber = 58.w;
double noVerticalNumber = 28.w;
if (isIos) {
noVerticalNumber = 50.w;
}
upperBound = ScreenUtil().screenWidth - (isVertical ? isVerticalNumber : noVerticalNumber);
lowerBound = isVertical ? 34.w : 18.w;
break;
case KeyboardType.INPUT_TYPE:
//
upperBound = ScreenUtil().screenWidth - (isIos ? 115.w : 95.w);
lowerBound = 18.w;
break;
case KeyboardType.BOTTOM_SELECTION:
upperBound = ScreenUtil().screenWidth;
lowerBound = isVertical ? 34.w : 18.w;
break;
}
upperBound = widget.maxWidth ?? upperBound;
_animationController = AnimationController(
value: graffitiHander.state.annotationSwitch ? upperBound : lowerBound, //
duration: const Duration(milliseconds: 300),
lowerBound: lowerBound,
upperBound: upperBound,
vsync: this,
)..addListener(toUp);
_annotationsListener = graffitiHander.addListener((state) {
graffitiSwitch = state;
if (state.annotationSwitch) {
bgc = const Color.fromRGBO(51, 57, 62, 1);
// toUp();
_animationController.forward();
} else {
_animationController.reverse();
setTimeOut(300, () => bgc = null);
}
});
super.initState();
}
@override
void dispose() {
_annotationsListener();
_animationController
..removeListener(toUp)
..dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
ScreenDirection _screenDirection = _preferenceModel.screenDirection;
bool isVertical = _screenDirection == ScreenDirection.VERTICAL_SCREEN; //
// print('当前屏幕情况:${graffitiSwitch.openBrush}');
// print(isVertical);
AnnotationGraffitiSwitch _graffitiSwitch = ref.watch(annotationGraffitiSwitchProvider);
double barrierSize = ScreenUtil().screenWidth / (isVertical ? 20 : 6);
Color actionColor = Colors.white;
Color defaultColor = Color.fromRGBO(132, 146, 163, 1);
return OrientationBuilder(
builder: (BuildContext context, Orientation orientation) {
bool isVertical = orientation == Orientation.portrait;
double iconSize = (isVertical ? 32 : 28).sp;
return Container(
height: 52.h,
// width: widget.homework ? double.infinity : _animationController.value,
width: _animationController.value,
color: widget.homework ? Color.fromRGBO(51, 57, 62, 0.2) : bgc,
padding: EdgeInsets.symmetric(vertical: 1.h),
child: widget.homework
? Row(
children: [
SizedBox(width: barrierSize + 20.w),
InkWell(
onTap: () {
easyThrottle('setSwitchBrush',
() => ref.read(annotationGraffitiSwitchProvider.notifier).setSwitchBrush());
},
child: Icon(const IconData(0xe623, fontFamily: "AlibabaIcon"),
size: iconSize, color: _graffitiSwitch.openBrush ? actionColor : defaultColor),
),
SizedBox(width: 24.w),
InkWell(
onTap: () {
eventFire(model: BottomAnnotationSwitchCleanall(previousStep: true));
},
child: Icon(IconData(0xe61d, fontFamily: "AlibabaIcon"), size: iconSize, color: defaultColor),
),
const Expanded(child: SizedBox()),
InkWell(
onTap: () {
easyThrottle('setSwitchMagnifier',
() => ref.read(annotationGraffitiSwitchProvider.notifier).setMagnifier());
},
// IconData(0xe62f, fontFamily: "AlibabaIcon")
child: Icon(IconData(0xe634, fontFamily: "AlibabaIcon"),
size: iconSize, color: _graffitiSwitch.magnifier ? actionColor : defaultColor),
),
SizedBox(width: 24.w),
InkWell(
onTap: () {
eventFire(model: BottomAnnotationSwitchCleanall(cleanAll: true));
},
child: Icon(IconData(0xe61f, fontFamily: "AlibabaIcon"), size: iconSize, color: defaultColor),
),
SizedBox(width: 24.w),
InkWell(
onTap: () {
easyThrottle(
'setSwitchMagnifier',
() => ref.read(annotationGraffitiSwitchProvider.notifier).setTrajectory(),
);
},
child: Icon(
IconData(0xe629, fontFamily: "AlibabaIcon"),
size: iconSize,
color: _graffitiSwitch.trajectoryDisplay ? actionColor : defaultColor,
),
),
SizedBox(width: isIos ? 40.w : 50.w),
],
)
: Stack(
alignment: const FractionalOffset(0, 0.5),
children: [
if (bgc != null)
Row(
children: [
SizedBox(width: barrierSize + 20.w),
InkWell(
onTap: () {
easyThrottle('setSwitchBrush',
() => ref.read(annotationGraffitiSwitchProvider.notifier).setSwitchBrush());
},
child: Icon(const IconData(0xe623, fontFamily: "AlibabaIcon"),
size: iconSize, color: _graffitiSwitch.openBrush ? actionColor : defaultColor),
),
SizedBox(width: 24.w),
InkWell(
onTap: () {
eventFire(model: BottomAnnotationSwitchCleanall(previousStep: true));
},
child:
Icon(IconData(0xe61d, fontFamily: "AlibabaIcon"), size: iconSize, color: defaultColor),
),
//
// InkWell(
// onTap: () {
// easyThrottle(
// 'setSwitchEraser', () => ref.read(annotationGraffitiSwitchProvider.notifier).setSwitchEraser());
// },
// child: Icon(const IconData(0xe61c, fontFamily: "AlibabaIcon"),
// color: _graffitiSwitch.openEraser ? Theme.of(context).primaryColor : Colors.white),
// ),
const Expanded(child: SizedBox()),
InkWell(
onTap: () {
easyThrottle('setSwitchMagnifier',
() => ref.read(annotationGraffitiSwitchProvider.notifier).setMagnifier());
},
child: Icon(IconData(0xe62f, fontFamily: "AlibabaIcon"),
size: iconSize, color: _graffitiSwitch.magnifier ? actionColor : defaultColor),
),
SizedBox(width: 24.w),
InkWell(
onTap: () {
eventFire(model: BottomAnnotationSwitchCleanall(cleanAll: true));
},
child:
Icon(IconData(0xe61f, fontFamily: "AlibabaIcon"), size: iconSize, color: defaultColor),
),
// SizedBox(width: 24.w),
// InkWell(
// onTap: (){
// eventFire(model:BottomAnnotationSwitchCleanall(uploadImage: true));
// },
// child: Column(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Icon(const IconData(0xe614, fontFamily: "AlibabaIcon"), color: Colors.white,size: 22.sp,),
// quickText('提交批注',color: Colors.white,size: 9.sp),
// ],
// )
// ),
SizedBox(width: isIos ? 40.w : 26.w),
],
),
InkWell(
onTap: () {
easyThrottle('setSwitchMarkingGraffiti', () {
if ([upperBound, lowerBound].contains(_animationController.value)) {
ref
.read(annotationGraffitiSwitchProvider.notifier)
.setSwitch(!graffitiSwitch.annotationSwitch);
}
});
},
child: Container(
// width: isVertical ? 34.w : 16.w,
width: barrierSize,
padding: EdgeInsets.only(top: 4.h, bottom: 4.h, right: 3.w),
alignment: Alignment.centerRight,
decoration: BoxDecoration(
color: const Color.fromRGBO(253, 147, 21, 1),
borderRadius: BorderRadius.only(
topRight: Radius.circular(30.sp),
bottomRight: Radius.circular(30.sp),
),
),
child: Icon(
!graffitiSwitch.annotationSwitch
? const IconData(0xe622, fontFamily: "AlibabaIcon")
: const IconData(0xe621, fontFamily: "AlibabaIcon"),
color: Colors.white,
size: isVertical ? 20.sp : 26.sp,
),
),
)
],
),
);
},
);
}
void toUp() {
toUpState(setState, () {}, mounted);
}
}

View File

@ -24,8 +24,7 @@ void main() {
WidgetsFlutterBinding.ensureInitialized();
RouterManager.initRouter();
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
overlays: [SystemUiOverlay.top, SystemUiOverlay.bottom]); //
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.top, SystemUiOverlay.bottom]); //
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); //
// OrientationHelper.setEnabledSystemUIOverlays(SystemUiOverlay.values);
@ -81,7 +80,7 @@ class _MyAppState extends State<MyApp> {
splitScreenMode: true,
builder: (context1, child) {
return MaterialApp(
title: '远轩阅卷系统',
title: '学而有道阅卷',
navigatorKey: TheGlobal.navigatorKey,
debugShowCheckedModeBanner: false,
// locale: const Locale('zh', 'CN'), // ,

View File

@ -0,0 +1,249 @@
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.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/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/job/job_student_goups.dart';
import 'package:marking_app/common/model/job/job_task_item.dart';
import 'package:marking_app/common/model/marking/marking_list_params.dart';
import 'package:marking_app/components/ReturnToHomepage.dart';
import 'package:marking_app/pages/homework_correction/widget/answer_trajectory_job.dart';
import 'package:marking_app/pages/homework_correction/widget/student_group_list.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/easy_refresh/MyEmptyWidget.dart';
import 'package:marking_app/utils/fast_data.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';
class AnswerTrajectory extends StatefulWidget {
const AnswerTrajectory({Key? key}) : super(key: key);
@override
State<AnswerTrajectory> createState() => _AnswerTrajectoryState();
}
class _AnswerTrajectoryState extends State<AnswerTrajectory>
with CommonMixin, SingleTickerProviderStateMixin {
late final EasyRefreshController refreshController;
late final EasyRefreshController refreshController2;
late String loginName;
List studentGroups = [];
List<JobTaskItem> jobList = [];
late TabController tabController;
int tabIndex = 0;
int page = 1;
int pageSize = 10;
int total = 0;
@override
void initState() {
super.initState();
refreshController = EasyRefreshController();
refreshController2 = EasyRefreshController();
tabController =
TabController(initialIndex: tabIndex, length: 2, vsync: this);
FastData fastData = FastData.getInstance();
fastData.getUser().then((value) {
if (value == null || value == '') return;
Map<String, dynamic> userInfo = json.decode(value);
setState(() {
loginName = userInfo['loginName'];
});
getStudentGroups();
getWorkList();
});
}
void getStudentGroups() async {
RestClient _client = await getClient();
BaseStructureResult<List<JobStudentGroups>> res =
await _client.getJobLevelStudentGroups(loginName);
setState(() {
if (res.code == 200) {
studentGroups = res.data!;
} else {
studentGroups = [];
}
});
refreshController.finishRefresh();
EasyLoading.dismiss();
}
void goNextPage(id, title) {
RouterManager.router.navigateTo(context,
'${RouterManager.jobPriorityReviewSetPath}?&groupId=$id&title=${Uri.encodeComponent(title)}&page=answerTrajectory',
transition: getTransition());
}
void getWorkList() async {
final MarkingListParams params = MarkingListParams(
page: page,
limit: pageSize,
pageType: 0,
markingType: 1,
);
print('params=${params.limit}&page=${params.page}');
RestClient client = await getClient();
BaseStructureResult<BasePageData<JobTaskItem>> res =
await client.getJobsByPage(params);
List<JobTaskItem> arr = [];
if (res.success) {
if (page == 1) {
arr = res.data!.items;
} else {
arr = [...jobList, ...res.data!.items];
}
total = res.data!.total;
} else {
jobList = [];
}
jobList = arr;
setState(() {});
refreshController2.finishRefresh();
EasyLoading.dismiss();
}
@override
void dispose() {
super.dispose();
refreshController.dispose();
refreshController2.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color.fromRGBO(245, 245, 245, 1),
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'答题轨迹',
style: TextStyle(fontSize: 14.sp, color: Color(0xFF333333)),
),
centerTitle: true,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios, color: Colors.black),
onPressed: () => Navigator.of(context).pop(),
),
actions: [
ReturnToHomepage(),
],
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 10.r,
),
Container(
padding: EdgeInsets.symmetric(horizontal: 14.r),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(width: 1.r, color: Color(0xFFCCCCCC)))),
child: TabBar(
onTap: (int val) {
print(val);
setState(() {
tabIndex = val;
});
/*EasyLoading.show(status: 'loading...');
if(val == 0){
getStudentGroups();
}*/
},
tabs: [
SizedBox(
width: (MediaQuery.of(context).size.width - 28.r) / 2,
child: Tab(
text: '按学生',
),
),
SizedBox(
width: (MediaQuery.of(context).size.width - 28.r) / 2,
child: Tab(
text: '按作业',
),
)
],
controller: tabController,
unselectedLabelStyle:
TextStyle(fontSize: 14.sp, color: Color(0xFF666666)),
labelStyle: TextStyle(
fontSize: 14.sp,
color: Color(0xFF6888FD),
),
isScrollable: true,
labelColor: Color(0xFF6888FD),
unselectedLabelColor: Color(0xFF666666),
indicatorSize: TabBarIndicatorSize.label,
labelPadding: const EdgeInsets.all(0),
),
),
Expanded(
child: Padding(
padding:
EdgeInsets.only(top: 15.r, left: 14.r, right: 14.r),
child:
tabIndex == 0
?
EasyRefresh(
firstRefresh: false,
taskIndependence: true,
controller: refreshController,
header: MaterialHeader(),
footer: TaurusFooter(),
onRefresh: () async {
getStudentGroups();
},
child: StudentGroupList(studentGroups, goNextPage,
rightBtn: Container(
margin: EdgeInsets.only(left: 5.r),
height: 20.r,
width: 55.r,
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(20.r)),
border: Border.all(
width: 1.r, color: Color(0xFFFF9800)),
),
child: Center(
child: Text(
'详情',
style: TextStyle(
fontSize: 10.sp, color: Color(0xFFFF9800)),
),
),
)),
):EasyRefresh(
firstRefresh: false,
taskIndependence: true,
controller: refreshController2,
header: MaterialHeader(),
footer: TaurusFooter(),
onRefresh: () async {
page = 1;
setState(() {});
getWorkList();
},
onLoad: () async {
if (jobList.length < total) {
EasyLoading.show(status: 'loading...');
page = page + 1;
getWorkList();
}
},
child:AnswerTrajectoryJob(jobList)),
),
)
],
),
);
}
}

View File

@ -0,0 +1,291 @@
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:marking_app/common/mixin/common.dart';
import 'package:marking_app/common/model/common/base_structure_result.dart';
import 'package:marking_app/common/model/job/job_concerned_with_student.dart';
import 'package:marking_app/common/model/job/job_concerned_with_student_params.dart';
import 'package:marking_app/common/model/job/job_task_item.dart';
import 'package:marking_app/components/ReturnToHomepage.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/easy_refresh/MyEmptyWidget.dart';
import 'package:marking_app/utils/index.dart';
import 'package:marking_app/utils/request/rest_client.dart';
class AnswerTrajectoryJobDetail extends StatefulWidget {
final int jobId;
final String jobName;
final String genderName;
const AnswerTrajectoryJobDetail(
{Key? key,
required this.jobId,
required this.jobName,
required this.genderName})
: super(key: key);
@override
State<AnswerTrajectoryJobDetail> createState() =>
_AnswerTrajectoryJobDetailState();
}
class _AnswerTrajectoryJobDetailState extends State<AnswerTrajectoryJobDetail>
with CommonMixin {
List<MarkingTasks> markList = [];
late MarkingTasks currentClass;
List<JobConcernedWithStudent> students = [];
late final EasyRefreshController refreshController;
@override
void initState() {
super.initState();
refreshController = EasyRefreshController();
EasyLoading.show(status: 'loading...');
getData();
}
void getData() async {
RestClient _client = await getClient();
BaseStructureResult<List<MarkingTasks>> res =
await _client.getJobListParticipateInClass(widget.jobId);
if (res.success) {
setState(() {
markList = res.data!;
if (markList.length > 0) {
currentClass = markList[0];
getStudentList();
}
});
}
}
void getStudentList() async {
RestClient _client = await getClient();
BaseStructureResult<List<JobConcernedWithStudent>> res =
await _client.getJobWithStudents(JobConcernedWithStudentParams([currentClass.id]));
if (res.success) {
setState(() {
students = res.data!;
});
}
refreshController.finishRefresh();
EasyLoading.dismiss();
}
@override
void dispose() {
super.dispose();
refreshController.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFF5F5F5),
appBar: AppBar(
centerTitle: true,
backgroundColor: Colors.white,
title: Text(
widget.jobName,
style: TextStyle(fontSize: 14.sp, color: Color(0xFF333333)),
overflow: TextOverflow.ellipsis,
),
leading: IconButton(
icon: Icon(Icons.arrow_back_ios, color: Colors.black),
onPressed: () => Navigator.of(context).pop(),
),
actions: [
ReturnToHomepage(),
],
),
body: Column(
children: [
SizedBox(
height: 10.r,
),
if (markList.length > 0)
Padding(
padding: EdgeInsets.symmetric(horizontal: 14.r),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: List.generate(markList.length, (index) {
MarkingTasks item = markList[index];
return InkWell(
onTap: (){
if(currentClass.id != item.id){
EasyLoading.show(status: 'loading...');
setState(() {
currentClass = item;
});
getStudentList();
}
},
child: Container(
padding: EdgeInsets.symmetric(
vertical: 5.r, horizontal: 10.r),
margin: EdgeInsets.only(
right: index < markList.length ? 8.r : 0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(4.r),
),
child: Center(
child: Text(
'${widget.genderName}${item.className}',
style: TextStyle(
fontSize: 10.sp,
color: currentClass.id == item.id
? Color(0xFF6888FD)
: Color(0xFF686868)),
),
),
),
);
})),
),
],
),
),
SizedBox(
height: 10.r,
),
Container(
height: 1.r,
color: Color(0xFFCCCCCC),
),
students.length>0? Expanded(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 14.r, horizontal: 14.r),
child: EasyRefresh(
firstRefresh: true,
taskIndependence: true,
controller: refreshController,
header: MaterialHeader(),
footer: TaurusFooter(),
onRefresh: () async {
getStudentList();
},
child: students.length > 0
? isPad()
? GridView(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10.r,
crossAxisSpacing: 10.r,
childAspectRatio: 556 / 112,
),
children: List.generate(students.length, (index) {
var item = students[index];
return InkWell(
onTap: (){
RouterManager.router.navigateTo(
context,
RouterManager.quickCheckPersonalPath +
'?jobId=${widget.jobId}&studentId=${item.studentId}',
transition: getTransition(),
);
// RouterManager.router.navigateTo(context,
// '${RouterManager.jobPersonalDetailPath}?studentId=${item.studentId}&studentName=${Uri.encodeComponent(item.studentName)}');
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10.r),
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(10.r)),
color: Colors.white,
),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
item.studentName,
style: TextStyle(
fontSize: 12.sp,
color: Color(0xFF6888FD)),
)),
Container(
height: 20.r,
width: 70.r,
decoration: BoxDecoration(
border: Border.all(width: 1.r,color: Color(0xFFFFA41E)),
borderRadius: BorderRadius.all(Radius.circular(20.r)),
),
child: Center(child: Text('详情',style: TextStyle(fontSize: 10.r,color: Color(0xFFFFA41E))),
)),
],
),
),
);
}),
)
: ListView.builder(
itemBuilder: (context, index) {
var item = students[index];
return InkWell(
onTap: (){
RouterManager.router.navigateTo(
context,
RouterManager.quickCheckPersonalPath +
'?jobId=${widget.jobId}&studentId=${item.studentId}',
transition: getTransition(),
);
// RouterManager.router.navigateTo(context,
// '${RouterManager.jobPersonalDetailPath}?studentId=${item.studentId}&studentName=${Uri.encodeComponent(item.studentName)}');
},
child: Container(
padding: EdgeInsets.symmetric(
vertical: 20.r, horizontal: 15.r),
margin: EdgeInsets.only(bottom: 15.r),
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(10.r)),
color: Colors.white,
),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
item.studentName,
style: TextStyle(
fontSize: 12.sp,
color: Color(0xFF6888FD)),
)),
Container(
height: 24.r,
width: 72.r,
decoration: BoxDecoration(
border: Border.all(width: 1.r,color: Color(0xFFFFA41E)),
borderRadius: BorderRadius.all(Radius.circular(20.r)),
),
child: Center(child: Text('详情',style: TextStyle(fontSize: 10.r,color: Color(0xFFFFA41E))),
)),
],
),
),
);
},
itemCount: students.length,
)
: MyEmptyWidget(),
),
),
):MyEmptyWidget(),
],
),
);
}
}

View File

@ -0,0 +1,25 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class ImageDialog{
static void showImgDialog(BuildContext context,String imgUrl) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
// insetPadding: EdgeInsets.symmetric(vertical: 10.r,horizontal: 45.r),
backgroundColor: Colors.transparent,
contentPadding: EdgeInsets.all(0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15.r))),
content: Container(
width: MediaQuery.of(context).size.width - 48.r,
// height: MediaQuery.of(context).size.height * 0.4,
color: Colors.white,
// child: PhotoView(imageProvider: NetworkImage(imgUrl),backgroundDecoration: BoxDecoration(color: Colors.transparent),)),
child: Image.network(imgUrl)),
);
},
);
}
}

View File

@ -21,12 +21,7 @@ class TrajectoryView extends StatefulHookConsumerWidget {
final double boxHeight;
final String questionNumber;
final JobNoteTakingTrajectory trajectory;
const TrajectoryView(
{required this.trajectory,
required this.questionNumber,
required this.boxHeight,
required this.boxWidth,
super.key});
const TrajectoryView({required this.trajectory, required this.questionNumber, required this.boxHeight, required this.boxWidth, super.key});
@override
TrajectoryViewState createState() => TrajectoryViewState();
@ -152,15 +147,11 @@ class TrajectoryViewState extends ConsumerState<TrajectoryView> {
///
trajectorys
..add(GestureRecording(
data: Offset(2.w, trajectory.pictureQuestionTop), scopeBox: true, annotationSwitch: false, eraser: false))
..add(GestureRecording(data: Offset(2.w, trajectory.pictureQuestionTop), scopeBox: true, annotationSwitch: false, eraser: false))
///
..add(GestureRecording(
data: Offset(imagInfoModel!.scaleWidth! - 4.w, trajectory.pictureQuestionTop),
scopeBox: true,
annotationSwitch: false,
eraser: false))
data: Offset(imagInfoModel!.scaleWidth! - 4.w, trajectory.pictureQuestionTop), scopeBox: true, annotationSwitch: false, eraser: false))
///
..add(GestureRecording(
@ -171,8 +162,7 @@ class TrajectoryViewState extends ConsumerState<TrajectoryView> {
///
..add(GestureRecording(
data: Offset(
imagInfoModel!.scaleWidth! - 4.w, trajectory.pictureQuestionTop + trajectory.pictureQuestionHeight),
data: Offset(imagInfoModel!.scaleWidth! - 4.w, trajectory.pictureQuestionTop + trajectory.pictureQuestionHeight),
scopeBox: true,
annotationSwitch: false,
eraser: false));
@ -181,14 +171,26 @@ class TrajectoryViewState extends ConsumerState<TrajectoryView> {
ref.read(jobDrawingTrajectoryProvider.notifier).setVal(trajectorys);
});
if (lattices.isNotEmpty) {
Map<int, List<Lattices>> map = new Map.fromIterable(lattices,
key: (key) => key.stroke,
value: (value) {
return lattices.where((item) => item.stroke == value.stroke).toList()
..sort((a, b) => a.time.compareTo(b.time));
});
// Map<int, List<Lattices>> map = new Map.fromIterable(lattices,
// key: (key) => key.stroke,
// value: (value) {
// return lattices.where((item) => item.stroke == value.stroke).toList()
// ..sort((a, b) => a.time.compareTo(b.time));
// });
var map = Map<int, List<Lattices>>();
for (var i = 0; i < lattices.length; i++) {
Lattices item = lattices[i];
if (!map.containsKey(item.stroke)) map[item.stroke] = [];
map[item.stroke]!.add(item); //
}
List<int> keys = map.keys.toList();
for (var i = 0; i < keys.length; i++) {
int theKey = keys[i];
map[theKey]!.sort((a, b) => a.time.compareTo(b.time));
}
for (var i = 0; i < keys.length; i++) {
int theKey = keys[i];
int? nextKey = i + 1 < keys.length ? keys[i + 1] : null;
@ -199,8 +201,7 @@ class TrajectoryViewState extends ConsumerState<TrajectoryView> {
double theX = e.x * imagInfoModel!.scale!;
double theY = e.y * imagInfoModel!.scale! + spacingHeight;
return GestureRecording(
eraser: false, data: Offset(theX, theY), usageTime: e.time.toInt(), annotationSwitch: false);
return GestureRecording(eraser: false, data: Offset(theX, theY), usageTime: e.time.toInt(), annotationSwitch: false);
}).toList()
..add(GestureRecording(eraser: false, annotationSwitch: false));
//
@ -223,15 +224,14 @@ class TrajectoryViewState extends ConsumerState<TrajectoryView> {
var zhixinCall = () async {
if (mounted) {
print('执行添加笔画${i},${j}');
// print('执行添加笔画${i},${j}');
trajectorys = List.from(trajectorys)..add(theRecording);
ref.read(jobDrawingTrajectoryProvider.notifier).setVal(trajectorys);
}
if (duration2 == null && nextStrokesData != null) {
//
Lattices minLattices = nextStrokesData.reduce((e1, e2) => e1.time < e2.time ? e1 : e2);
differenceInMilliseconds =
(Duration(milliseconds: minLattices.time.toInt()) - duration1).inMilliseconds;
differenceInMilliseconds = (Duration(milliseconds: minLattices.time.toInt()) - duration1).inMilliseconds;
await Future.delayed(Duration(milliseconds: differenceInMilliseconds)); //
}
};

View File

@ -290,19 +290,28 @@ Widget $dropdownBoxSwitchStudentsOrTypeView(BuildContext context, {required Func
var _currentTab = _useSwitchStudentAndType.currentTab.value;
var _pageIndex = _currentTab?.pageIndex;
if (_currentTab == null || _pageIndex == null) return;
var params = MarkingTextQuestionJobTabParamsBus(taskId, _pageIndex);
if (_currentTab.finishCount + 1 == _currentTab.total) {
var _currentTabNew =
_useSwitchStudentAndType.tabs.value.firstWhereOrNull((e) => e.pageIndex != _currentTab.pageIndex && e.finishCount != e.total);
//
if (_currentTabNew != null) params.pageIndex = _currentTabNew.pageIndex;
}
var _theCurrentPage = _useSwitchStudentAndType.tabs.value.firstWhereOrNull((element) => element.pageIndex == _pageIndex);
if (_theCurrentPage != null) {
_theCurrentPage.finishCount += 1;
_useSwitchStudentAndType.tabs.value = _useSwitchStudentAndType.tabs.value.map((e) => JobPageTab.fromJson(e.toJson())).toList();
}
_useSwitchStudentAndType.eventFire(model: params);
var theLastQuestion = _currentTab.finishCount + 1 == _currentTab.total; //
_useSwitchStudentAndType
.refreshQuestionTypeData(context, taskId: taskId, exitCallback: exitCallback, getNewData: theLastQuestion)
.then((value) {
var params = MarkingTextQuestionJobTabParamsBus(taskId, _pageIndex);
if (_currentTab.finishCount < _currentTab.total) {
if (_currentTab.finishCount + 1 == _currentTab.total) {
var _currentTabNew =
_useSwitchStudentAndType.tabs.value.firstWhereOrNull((e) => e.pageIndex != _currentTab.pageIndex && e.finishCount != e.total);
//
if (_currentTabNew != null) params.pageIndex = _currentTabNew.pageIndex;
}
var _theCurrentPage = _useSwitchStudentAndType.tabs.value.firstWhereOrNull((element) => element.pageIndex == _pageIndex);
if (_theCurrentPage != null) {
_theCurrentPage.finishCount += 1;
_useSwitchStudentAndType.tabs.value = _useSwitchStudentAndType.tabs.value.map((e) => JobPageTab.fromJson(e.toJson())).toList();
}
}
_useSwitchStudentAndType.eventFire(model: params);
});
break;
default:
}
@ -361,42 +370,60 @@ Widget $dropdownBoxSwitchStudentsOrTypeView(BuildContext context, {required Func
Expanded(flex: 1, child: SizedBox()),
Expanded(
flex: 4,
child: Container(
padding: EdgeInsets.only(left: 10.w),
decoration: BoxDecoration(
color: Color.fromRGBO(244, 244, 244, 1),
borderRadius: BorderRadius.circular(4.r),
),
child: DropdownButton(
onTap: () {
//
_useSwitchStudentAndType.getDataForStudents(taskId: taskId);
},
padding: EdgeInsets.only(right: 4.w),
icon: Icon(Icons.keyboard_arrow_down_rounded),
value: _useSwitchStudentAndType.currentStudent.value?.studentId,
underline: Container(),
isExpanded: true,
items: _useSwitchStudentAndType.studentData.value.map((e) {
return DropdownMenuItem(
child: quickText(e.studentName, color: Color.fromRGBO(79, 79, 79, 1), size: 14.sp),
value: e.studentId,
);
}).toList(),
hint: Text('请选择学生'), //
onChanged: (value) {
JobConcernedWithStudent? currentStudent = _useSwitchStudentAndType.currentStudent.value;
if (currentStudent?.studentId == value) return;
_useSwitchStudentAndType.studentBusInfo.value = null; // BUS通知记录
_useSwitchStudentAndType.currentStudent.value =
_useSwitchStudentAndType.studentData.value.firstWhereOrNull((element) => element.studentId == value);
},
),
child: Stack(
children: [
Container(
padding: EdgeInsets.only(left: 10.w),
decoration: BoxDecoration(
color: Color.fromRGBO(244, 244, 244, 1),
borderRadius: BorderRadius.circular(4.r),
),
child: DropdownButton(
onTap: () {
//
_useSwitchStudentAndType.getDataForStudents(taskId: taskId);
},
padding: EdgeInsets.only(right: 4.w),
icon: Icon(Icons.keyboard_arrow_down_rounded),
value: _useSwitchStudentAndType.currentStudent.value?.studentId,
underline: Container(),
isExpanded: true,
items: _useSwitchStudentAndType.studentData.value.map((e) {
return DropdownMenuItem(
child: quickText(e.studentName, color: Color.fromRGBO(79, 79, 79, 1), size: 14.sp),
value: e.studentId,
);
}).toList(),
hint: Text('请选择学生'), //
onChanged: (value) {
JobConcernedWithStudent? currentStudent = _useSwitchStudentAndType.currentStudent.value;
if (currentStudent?.studentId == value) return;
_useSwitchStudentAndType.studentBusInfo.value = null; // BUS通知记录
_useSwitchStudentAndType.currentStudent.value =
_useSwitchStudentAndType.studentData.value.firstWhereOrNull((element) => element.studentId == value);
},
),
),
Positioned(
left: 2.w,
child: Stack(
alignment: const FractionalOffset(0.52, 0.24),
children: [
Icon(
const IconData(0xe63d, fontFamily: "AlibabaIcon"),
size: 12.sp,
color: _useSwitchStudentAndType.isFirst.value ? Color.fromRGBO(76, 199, 147, 1) : Color.fromRGBO(164, 164, 164, 1),
),
quickText('优先', size: 4.sp, color: Colors.white),
],
),
),
],
),
),
Expanded(flex: 1, child: SizedBox()),
Expanded(
flex: 4,
flex: isPad() ? 4 : 5,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,
@ -415,9 +442,7 @@ Widget $dropdownBoxSwitchStudentsOrTypeView(BuildContext context, {required Func
'DO_PAPERS_JOB_CONTINUE_TO_REVIEW',
() {
var _currentTabNew = _useSwitchStudentAndType.tabs.value.firstWhere((e) => e.finishCount < e.total);
_useSwitchStudentAndType.eventFire(
model: MarkingTextQuestionJobTabParamsBus(taskId, _currentTabNew.pageIndex),
);
_useSwitchStudentAndType.eventFire(model: MarkingTextQuestionJobTabParamsBus(taskId, _currentTabNew.pageIndex));
},
),
child: quickText(
@ -455,54 +480,8 @@ Widget $dropdownBoxSwitchStudentsOrTypeView(BuildContext context, {required Func
),
),
),
Stack(
alignment: const FractionalOffset(0.52, 0.24),
children: [
Icon(
const IconData(0xe63d, fontFamily: "AlibabaIcon"),
size: 12.sp,
color: _useSwitchStudentAndType.isFirst.value ? Color.fromRGBO(76, 199, 147, 1) : Color.fromRGBO(164, 164, 164, 1),
),
quickText('优先', size: 4.sp, color: Colors.white),
],
),
],
),
// InkWell(
// onTap: () => easyThrottle(
// 'prioritize_homework_review',
// () => !_useSwitchStudentAndType.isFirst.value
// ? _useSwitchStudentAndType.jobPriorityReviewJoin(jobId)
// : _useSwitchStudentAndType.jobPriorityReviewCancel(jobId)),
// child:
// Row(
// crossAxisAlignment: CrossAxisAlignment.center,
// mainAxisAlignment: MainAxisAlignment.start,
// children: [
// Stack(
// alignment: const FractionalOffset(0.52, 0.24),
// children: [
// Icon(
// const IconData(0xe63d, fontFamily: "AlibabaIcon"),
// size: 12.sp,
// color: _useSwitchStudentAndType.isFirst.value
// ? Color.fromRGBO(76, 199, 147, 1)
// : Color.fromRGBO(164, 164, 164, 1),
// ),
// quickText('优先', size: 4.sp, color: Colors.white),
// ],
// ),
// SizedBox(width: 1.2.w),
// quickText(
// '优先批阅',
// size: 10.sp,
// color: _useSwitchStudentAndType.isFirst.value
// ? Color.fromRGBO(76, 199, 147, 1)
// : Color.fromRGBO(164, 164, 164, 1),
// ),
// ],
// ),
// ),
),
],
),
@ -541,7 +520,14 @@ class _EexamPaperAndScoringViewState extends ConsumerState<ExamPaperAndScoringVi
var theEventVal = eventVal as MarkingTextQuestionJobTabParamsBus;
bool? isDefaultFirst;
if (theJobData != null) {
isDefaultFirst = theJobData!.pageIndex < theEventVal.pageIndex;
isDefaultFirst = theJobData!.pageIndex == theEventVal.pageIndex ? null : theJobData!.pageIndex < theEventVal.pageIndex;
} else {
if (synchroTabs?.tabs.isNotEmpty ?? false) {
var _theTab = synchroTabs?.tabs.firstWhereOrNull((e) => e.pageIndex == theEventVal.pageIndex);
if (_theTab != null && _theTab.finishCount == _theTab.total) {
isDefaultFirst = false;
}
}
}
ref.read(doJobObtainGradingDataProvider.notifier).setVal(MarkingTextQuestionJobTabParams(
pageIndex: theEventVal.pageIndex,
@ -579,8 +565,8 @@ class _EexamPaperAndScoringViewState extends ConsumerState<ExamPaperAndScoringVi
var jobDetails = _result.data;
theJobData = jobDetails;
if (jobDetails != null) {
jobDetails.previousPageIndex = synchroTabs?.getPreviousPageIndex(jobDetails.pageIndex - 1);
jobDetails.nextPageIndex = synchroTabs?.getNextPageIndex(jobDetails.pageIndex - 1);
jobDetails.previousPageIndex = synchroTabs?.getPreviousPageIndex(jobDetails.pageIndex);
jobDetails.nextPageIndex = synchroTabs?.getNextPageIndex(jobDetails.pageIndex);
//
try {
//
@ -618,8 +604,15 @@ class _EexamPaperAndScoringViewState extends ConsumerState<ExamPaperAndScoringVi
pageIndex: jobData.pageIndex,
nextPageIndex: jobData.nextPageIndex,
previousPageIndex: jobData.previousPageIndex,
isDefaultFirst: true,
);
if (jobData.nextId == 0 && (synchroTabs?.tabs.isNotEmpty ?? false)) {
var _pageIndex = jobData.pageIndex;
var _tabIndex = synchroTabs!.tabs.indexWhere((e) => e.pageIndex == _pageIndex);
if (_tabIndex != -1 && _tabIndex + 1 <= synchroTabs!.tabs.length - 1) {
model.isDefaultFirst = true;
}
}
if (model.paperId == 0 && jobData.nextPageIndex != null) {
//
model.paperId = null;
@ -635,8 +628,16 @@ class _EexamPaperAndScoringViewState extends ConsumerState<ExamPaperAndScoringVi
paperId: jobData.prevId,
nextPageIndex: jobData.nextPageIndex,
previousPageIndex: jobData.previousPageIndex,
isDefaultFirst: false,
);
if (jobData.prevId == 0 && (synchroTabs?.tabs.isNotEmpty ?? false)) {
var _pageIndex = jobData.pageIndex;
var _tabIndex = synchroTabs!.tabs.indexWhere((e) => e.pageIndex == _pageIndex);
if (_tabIndex != -1 && _tabIndex - 1 >= 0 && _tabIndex - 1 <= synchroTabs!.tabs.length - 1) {
model.isDefaultFirst = false;
}
}
if (model.paperId == 0 && jobData.previousPageIndex != null) {
model.paperId = null;
model.pageIndex = jobData.previousPageIndex!;
@ -862,16 +863,15 @@ Widget $examPaperAndScoringKeyboardView(
],
),
),
if (question.accuracy > 0)
Padding(
padding: EdgeInsets.only(bottom: 1.5.h),
child: quickText(
'正确率:${getDoubleRemoveZero(question.accuracy, question.accuracy.toString())}%',
size: 8.sp,
color: Colors.white,
align: TextAlign.end,
),
)
Padding(
padding: EdgeInsets.only(bottom: 1.5.h),
child: quickText(
'正确率:${getDoubleRemoveZero(question.accuracy, question.accuracy.toString())}%',
size: 8.sp,
color: Colors.white,
align: TextAlign.end,
),
)
],
),
),

View File

@ -99,8 +99,12 @@ class UseSwitchStudentAndType with CommonMixin, EventBusMixin {
}
/// tab类型数据
Future<JobPageTab?> refreshQuestionTypeData(BuildContext context, {required int taskId, required Function() exitCallback}) async {
List<JobPageTab>? tabDatas = await getDataForTestpaper(taskId: taskId, synchronization: false);
Future<JobPageTab?> refreshQuestionTypeData(BuildContext context,
{required int taskId, required Function() exitCallback, bool getNewData = true}) async {
List<JobPageTab>? tabDatas = tabs.value;
if (getNewData) {
tabDatas = await getDataForTestpaper(taskId: taskId, synchronization: false);
}
if (tabDatas?.isNotEmpty ?? false) {
JobPageTab? tabJob = tabDatas!.firstWhereOrNull((e) => e.finishCount < e.total);
if (tabJob == null && !exitPromptFlag.value) {
@ -124,9 +128,20 @@ class UseSwitchStudentAndType with CommonMixin, EventBusMixin {
exitCallback();
} else {
//
if (!getNewData) return tabJob;
tabs.value = tabDatas;
if (tabJob != null) currentTab.value = tabJob;
if (tabJob == null && exitPromptFlag.value) ToastUtils.showSuccess('最后一题提交成功');
if (tabJob == null && exitPromptFlag.value) {
var _thePageIndex = currentTab.value?.pageIndex;
if (_thePageIndex != null) {
var _theIndex = tabDatas.indexWhere((e) => e.pageIndex == _thePageIndex);
if (_theIndex != -1 && _theIndex < tabDatas.length - 1) {
currentTab.value = tabDatas[_theIndex + 1];
return tabJob;
}
}
// ToastUtils.showSuccess('最后一题提交成功');
}
return tabJob;
}
}

View File

@ -7,6 +7,8 @@
* @Description:
*/
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
@ -16,7 +18,9 @@ import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:marking_app/common/config/request_config.dart';
import 'package:marking_app/common/model/event_bus/job_home_refresh_bus.dart';
import 'package:marking_app/common/model/job/job_task_item.dart';
import 'package:marking_app/pages/common/event_bus_mixin.dart';
import 'package:marking_app/pages/homework_correction/components/new_version_of_homework/homework_tasks_view_item.dart';
import 'package:marking_app/provider/review_provider.dart';
import 'package:marking_app/routes/RouterManager.dart';
@ -40,14 +44,7 @@ class HomeworkCorrection extends StatefulHookConsumerWidget {
}
class _HomeworkCorrectionState extends ConsumerState<HomeworkCorrection>
with
CommonMixin,
TickerProviderStateMixin,
RefreshDataHandle<JobTaskItem, MarkingListParams>,
AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
with CommonMixin, EventBusMixin, TickerProviderStateMixin, RefreshDataHandle<JobTaskItem, MarkingListParams> {
/* Tab控制器 */
late TabController _tabController;
late TabController _tabController2;
@ -127,6 +124,7 @@ class _HomeworkCorrectionState extends ConsumerState<HomeworkCorrection>
_tabController.dispose();
_refreshController1.dispose();
_refreshController2.dispose();
eventCancel();
super.dispose();
}
@ -152,8 +150,6 @@ class _HomeworkCorrectionState extends ConsumerState<HomeworkCorrection>
@override
Widget build(BuildContext context) {
super.build(context); //super.build(null)
return AnnotatedRegion(
value: const SystemUiOverlayStyle(
systemNavigationBarColor: Color(0xFF000000),
@ -176,7 +172,19 @@ class _HomeworkCorrectionState extends ConsumerState<HomeworkCorrection>
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(flex: 1, child: SizedBox()),
Expanded(
flex: 1,
child: Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(left: 10.w),
child: InkWell(
onTap: () => easyThrottle('BACK_JOB_HOME', () => Navigator.of(context).pop()),
child: Icon(
Icons.arrow_back_ios_sharp,
size: 16.sp,
),
),
)),
Expanded(
flex: 4,
child: Container(
@ -226,9 +234,7 @@ class _HomeworkCorrectionState extends ConsumerState<HomeworkCorrection>
child: quickText(
'待批阅',
size: 14.sp,
color: _tabIndex == 0
? Theme.of(context).primaryColor
: const Color.fromRGBO(80, 94, 110, 1),
color: _tabIndex == 0 ? Theme.of(context).primaryColor : const Color.fromRGBO(80, 94, 110, 1),
fontWeight: _tabIndex == 0 ? FontWeight.bold : null,
),
),
@ -246,9 +252,7 @@ class _HomeworkCorrectionState extends ConsumerState<HomeworkCorrection>
child: quickText(
'已批阅',
size: 14.sp,
color: _tabIndex == 1
? Theme.of(context).primaryColor
: const Color.fromRGBO(80, 94, 110, 1),
color: _tabIndex == 1 ? Theme.of(context).primaryColor : const Color.fromRGBO(80, 94, 110, 1),
fontWeight: _tabIndex == 1 ? FontWeight.bold : null,
),
),
@ -257,32 +261,10 @@ class _HomeworkCorrectionState extends ConsumerState<HomeworkCorrection>
),
),
),
Expanded(
flex: 1,
child: InkWell(
onTap: () {
RouterManager.router
.navigateTo(context, RouterManager.jobStudentGroupPath, transition: getTransition());
},
child: Icon(IconData(0xe63e, fontFamily: "AlibabaIcon"),
color: Color.fromRGBO(44, 48, 63, 1), size: 24.sp),
),
),
Expanded(flex: 1, child: SizedBox()),
],
),
),
/* Row(
children: [
InkWell(
onTap: (){
},
child: Text('历史作业'),
),
],
),*/
if (_tabIndex == 1)
$CompletedJobConditionFilter(
controller: _tabController2,
@ -317,6 +299,9 @@ class _HomeworkCorrectionState extends ConsumerState<HomeworkCorrection>
data: markingDatas1,
onLoad: onMyLoad,
onRefresh: onMyRefresh,
eventFire: () {
eventFire(model: JobHomeRefreshBus());
},
),
$EasyRefresh(
controller: _refreshController2,
@ -325,6 +310,9 @@ class _HomeworkCorrectionState extends ConsumerState<HomeworkCorrection>
data: markingDatas2,
onLoad: onMyLoad,
onRefresh: onMyRefresh,
eventFire: () {
eventFire(model: JobHomeRefreshBus());
},
),
],
),
@ -346,6 +334,7 @@ Widget $easyRefresh({
required EasyRefreshController controller,
required Future<void> Function(EasyRefreshController controller, MarkingListParams params, int tab) onRefresh,
required Future<void> Function(EasyRefreshController controller, MarkingListParams params, int tab) onLoad,
required Function eventFire,
required MarkingListParams params,
required List<JobTaskItem> data,
required int tab,
@ -378,7 +367,10 @@ Widget $easyRefresh({
return HomeworkTasksViewItem(
completed: completed,
jobTaskItem: data[index],
call: () => controller.callRefresh(),
call: () {
controller.callRefresh();
eventFire();
},
);
},
itemCount: data.length,
@ -426,9 +418,7 @@ Widget $reviewedItem(BuildContext context, {required JobTaskItem jobTaskItem}) {
alignment: Alignment.center,
padding: EdgeInsets.only(left: 2.w),
decoration: BoxDecoration(
color: jobTaskItem.markingTypeEnum.name == '作业'
? const Color.fromRGBO(104, 136, 253, 1)
: const Color.fromRGBO(255, 175, 56, 1),
color: jobTaskItem.markingTypeEnum.name == '作业' ? const Color.fromRGBO(104, 136, 253, 1) : const Color.fromRGBO(255, 175, 56, 1),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(14.r),
topRight: Radius.circular(3.r),
@ -489,8 +479,7 @@ Widget $reviewedItem(BuildContext context, {required JobTaskItem jobTaskItem}) {
onTap: () => easyThrottle('go_to_homework_report', () {
RouterManager.router.navigateTo(
context,
RouterManager.jobReportPagePath +
'?title=${Uri.encodeComponent(jobTaskItem.title)}&id=${jobTaskItem.id}',
RouterManager.jobReportPagePath + '?title=${Uri.encodeComponent(jobTaskItem.title)}&id=${jobTaskItem.id}',
transition: getTransition(),
);
}),
@ -533,8 +522,7 @@ Widget $theTabBar({required TabController controller, ValueChanged<int>? onTap,
if (customTime.endDate != null) {
// print(customTime.startDate!.year == customTime.endDate!.year);
if (!isPad() && customTime.startDate!.year == customTime.endDate!.year) {
customTimeStr =
customTime.startDate.toString().substring(5, 10) + '~${customTime.endDate.toString().substring(5, 10)}';
customTimeStr = customTime.startDate.toString().substring(5, 10) + '~${customTime.endDate.toString().substring(5, 10)}';
} else {
customTimeStr += '~${customTime.endDate?.toString().substring(0, 10)}';
}

View File

@ -0,0 +1,861 @@
// import 'package:flutter/material.dart';
// import 'package:flutter/services.dart';
// import 'package:flutter_hooks/flutter_hooks.dart';
// import 'package:flutter_screenutil/flutter_screenutil.dart';
// import 'package:functional_widget_annotation/functional_widget_annotation.dart';
// import 'package:marking_app/common/mixin/common.dart';
// import 'package:marking_app/common/model/event_bus/job_home_refresh_bus.dart';
// import 'package:marking_app/common/model/marking/marking_list_params.dart';
// import 'package:marking_app/pages/common/event_bus_mixin.dart';
// import 'package:marking_app/routes/RouterManager.dart';
// import 'package:marking_app/utils/index.dart';
// import 'package:marking_app/utils/my_text.dart';
// import 'package:flutter_easyrefresh/easy_refresh.dart';
// import 'package:badges/badges.dart' as badges;
// part 'job_home.g.dart';
// class JobHome extends StatefulWidget {
// const JobHome({super.key});
// @override
// State<JobHome> createState() => _JobHomeState();
// }
// class _JobHomeState extends State<JobHome> with CommonMixin, EventBusMixin, AutomaticKeepAliveClientMixin {
// @override
// bool get wantKeepAlive => true;
// late LinkHeaderNotifier _linkNotifier;
// late ValueNotifier<bool> _secondFloorOpen;
// @override
// void initState() {
// getData();
// eventOn(callback: (JobHomeRefreshBus item) => getData());
// _linkNotifier = LinkHeaderNotifier();
// _secondFloorOpen = ValueNotifier<bool>(false);
// super.initState();
// }
// @override
// void dispose() {
// eventCancel();
// _linkNotifier.dispose();
// _secondFloorOpen.dispose();
// super.dispose();
// }
// Future<int> getData() async {
// try {
// var _client = await getClient();
// var _result = await _client.getJobsByPage(MarkingListParams(
// isFinish: false,
// page: 1,
// limit: 1,
// pageType: 0,
// ));
// var data = _result.data?.total ?? 0;
// eventFire(model: QuantityToBeReviewedData(data));
// return data;
// } catch (e) {
// return 0;
// }
// }
// @override
// Widget build(BuildContext context) {
// super.build(context);
// return AnnotatedRegion(
// value: const SystemUiOverlayStyle(
// systemNavigationBarColor: Color(0xFF000000),
// systemNavigationBarDividerColor: null,
// statusBarColor: Colors.white,
// systemNavigationBarIconBrightness: Brightness.light,
// statusBarIconBrightness: Brightness.dark,
// statusBarBrightness: Brightness.light,
// ),
// child: SizedBox(
// height: ScreenUtil().screenHeight,
// width: ScreenUtil().screenWidth,
// child: Column(
// children: [
// //
// SecondFloorWidget(_linkNotifier, _secondFloorOpen, refreshCall: () => eventFire(model: JobHomeRefreshBus())),
// Expanded(
// child: EasyRefresh.custom(
// header: LinkHeader(
// _linkNotifier,
// extent: 70.0,
// triggerDistance: 70.0,
// completeDuration: Duration(milliseconds: 500),
// ),
// onRefresh: () async {
// if (_secondFloorOpen.value) return;
// // await Future.delayed(Duration(seconds: 2), () {
// // if (mounted) {
// // setState(() {
// // _count = 20;
// // });
// // }
// // });
// },
// onLoad: () async {
// // await Future.delayed(Duration(seconds: 2), () {
// // if (mounted) {
// // setState(() {
// // _count += 20;
// // });
// // }
// // });
// },
// slivers: <Widget>[
// SliverAppBar(
// expandedHeight: 300.h,
// pinned: true,
// floating: true,
// backgroundColor: Colors.red,
// flexibleSpace: FlexibleSpaceBar(
// centerTitle: false,
// title: Column(
// mainAxisSize: MainAxisSize.min,
// children: [
// SlidingData([
// EntranceModel(
// title: '作业批阅', image: 'assets/images/job_home_marking.png', navigationUrl: RouterManager.jobMainListPagePath),
// EntranceModel(
// title: '学生历史作业',
// image: 'assets/images/job_home_history.png',
// navigationUrl: '${RouterManager.jobStudentGroupPath}?page=history',
// ),
// EntranceModel(
// title: '知识点点掌握',
// image: 'assets/images/job_home_knowledge.png',
// navigationUrl: RouterManager.jobKnowledgePointsPath)
// ]),
// $TermRow([
// EntranceModel(
// title: '答题轨迹',
// image: 'assets/images/job_home_answer_record.png',
// navigationUrl: RouterManager.answerTrajectoryPath),
// EntranceModel(
// title: '优先批阅设定',
// image: 'assets/images/job_home_youxian.png',
// navigationUrl: '${RouterManager.jobStudentGroupPath}?page=set',
// )
// ], 0),
// ],
// )),
// ),
// SliverList(
// delegate: SliverChildBuilderDelegate(
// (context, index) {
// return Container(
// height: 40.h,
// color: Colors.amber,
// width: ScreenUtil().screenWidth,
// );
// },
// childCount: 10,
// ),
// ),
// ],
// ),
// ),
// ],
// ),
// ));
// }
// }
// class EntranceModel extends Object {
// String title;
// String image;
// String navigationUrl;
// EntranceModel({required this.title, required this.image, required this.navigationUrl});
// }
// class QuantityToBeReviewedData extends Object {
// int num;
// QuantityToBeReviewedData(this.num);
// }
// @swidget
// Widget $termRow(BuildContext context, List<EntranceModel> items, int data) {
// var leng = items.length;
// Widget childWidget;
// switch (leng) {
// case 1:
// childWidget = Row(children: [Expanded(child: $TermItem(items[0], data))]);
// break;
// case 2:
// childWidget = Row(children: [
// Expanded(flex: 9, child: $TermItem(items[0], data)),
// Expanded(flex: 1, child: SizedBox()),
// Expanded(flex: 9, child: $TermItem(items[1], data)),
// ]);
// break;
// case 3:
// double _theHeight = ScreenUtil().screenWidth / 19 + 54.h * 2;
// childWidget = Row(
// children: [
// Expanded(child: $TermItem(items[0], data, theHeight: _theHeight)),
// SizedBox(width: ScreenUtil().screenWidth / 19),
// Expanded(
// child: SizedBox(
// height: _theHeight,
// child: Column(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// $TermItem(items[1], data),
// $TermItem(items[2], data),
// ],
// ),
// ),
// ),
// ],
// );
// break;
// default:
// childWidget = Container();
// }
// return Container(padding: EdgeInsets.symmetric(horizontal: 14.w), child: childWidget);
// }
// @swidget
// Widget $termItem(BuildContext context, EntranceModel e, int data, {double? theHeight}) {
// bool isJob = e.title == '作业批阅';
// return Material(
// color: Colors.white,
// elevation: 3.r,
// shadowColor: const Color.fromRGBO(231, 231, 231, 1),
// borderRadius: BorderRadius.all(Radius.circular(8.r)),
// child: InkWell(
// onTap: () => easyThrottle('GO_TO_JOB_HOME_NAVIGATION', () {
// RouterManager.router.navigateTo(context, e.navigationUrl, transition: getTransition());
// }),
// // splashColor: splashColor,
// borderRadius: BorderRadius.all(Radius.circular(8.r)),
// child: badges.Badge(
// showBadge: isJob && data > 0,
// ignorePointer: false,
// badgeContent: quickText(data, color: Colors.white, size: 10.sp),
// badgeAnimation: badges.BadgeAnimation.rotation(
// animationDuration: Duration(seconds: 1),
// colorChangeAnimationDuration: Duration(seconds: 1),
// loopAnimation: false,
// curve: Curves.fastOutSlowIn,
// colorChangeAnimationCurve: Curves.easeInCubic,
// ),
// badgeStyle: badges.BadgeStyle(
// badgeColor: Color.fromRGBO(255, 105, 105, 1),
// shape: badges.BadgeShape.square,
// borderRadius: BorderRadius.only(topLeft: Radius.circular(10.r), topRight: Radius.circular(8.5.r), bottomRight: Radius.circular(8.5.r)),
// // borderSide: BorderSide(color: Colors.white, width: 2),
// elevation: 1,
// padding: EdgeInsets.symmetric(horizontal: isPad() ? 11.w : 16.w, vertical: 2.h),
// ),
// position: badges.BadgePosition.topEnd(top: 10.r, end: 10.r),
// child: Container(
// height: theHeight,
// padding: EdgeInsets.symmetric(vertical: 12.h),
// decoration: BoxDecoration(
// borderRadius: BorderRadius.all(Radius.circular(8.r)),
// // boxShadow: [
// // BoxShadow(
// // color: const Color.fromRGBO(231, 231, 231, 1),
// // offset: Offset(4.w, 6.h), //y轴偏移量
// // blurRadius: 8, //
// // spreadRadius: 0.2, //
// // )
// // ],
// // border: Border.all(width: 0.5.w, color: Color.fromARGB(255, 219, 226, 250)),
// ),
// alignment: Alignment.center,
// child: isJob
// ? Column(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Image.asset(e.image, height: 32.r, width: 32.r, fit: BoxFit.cover),
// SizedBox(height: 6.r),
// quickText(e.title, size: 12.sp, color: Color.fromRGBO(79, 79, 79, 1), fontWeight: FontWeight.w500),
// ],
// )
// : Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Image.asset(e.image, height: 32.r, width: 32.r, fit: BoxFit.cover),
// SizedBox(width: 6.r),
// quickText(e.title, size: 12.sp, color: Color.fromRGBO(79, 79, 79, 1), fontWeight: FontWeight.w500),
// ],
// ),
// ),
// )),
// );
// }
// class SlidingData extends HookWidget with EventBusMixin {
// final List<EntranceModel> items;
// SlidingData(this.items);
// @override
// Widget build(BuildContext context) {
// var dataNumber = useState<QuantityToBeReviewedData?>(null);
// useEffect(() {
// eventOn(callback: (QuantityToBeReviewedData data) => (dataNumber.value = data));
// return () {
// eventCancel();
// };
// }, []);
// return $TermRow(items, dataNumber.value?.num ?? 0);
// }
// }
// ///
// class SecondFloorWidget extends StatefulWidget {
// // Header连接通知器
// final LinkHeaderNotifier linkNotifier;
// //
// final ValueNotifier<bool> secondFloorOpen;
// final Function refreshCall;
// const SecondFloorWidget(this.linkNotifier, this.secondFloorOpen, {required this.refreshCall, Key? key}) : super(key: key);
// @override
// State<StatefulWidget> createState() => SecondFloorWidgetState();
// }
// class SecondFloorWidgetState extends State<SecondFloorWidget> {
// //
// final double _openSecondFloorExtent = 100.0;
// //
// double? _indicatorValue = 0.0;
// //
// double _secondFloor = 0.0;
// //
// bool _toggleAnimation = false;
// Duration _toggleAnimationDuration = Duration(milliseconds: 300);
// //
// bool _isOpen = false;
// RefreshMode get _refreshState => widget.linkNotifier.refreshState;
// double get _pulledExtent => widget.linkNotifier.pulledExtent;
// @override
// void initState() {
// widget.linkNotifier.addListener(onLinkNotify);
// super.initState();
// }
// void onLinkNotify() {
// setState(() {
// if (_refreshState == RefreshMode.armed || _refreshState == RefreshMode.refresh) {
// _indicatorValue = null;
// //
// if (widget.secondFloorOpen.value && !_toggleAnimation) {
// _isOpen = true;
// _secondFloor = MediaQuery.of(context).size.height - 60.h;
// _toggleAnimation = true;
// Future.delayed(_toggleAnimationDuration, () {
// if (mounted) {
// setState(() {
// _toggleAnimation = false;
// });
// }
// });
// }
// } else if (_refreshState == RefreshMode.refreshed || _refreshState == RefreshMode.done) {
// _indicatorValue = 1.0;
// } else {
// if (_refreshState == RefreshMode.inactive) {
// _indicatorValue = 0.0;
// _toggleAnimation = true;
// Future.delayed(_toggleAnimationDuration, () {
// if (mounted) {
// setState(() {
// _toggleAnimation = false;
// });
// }
// });
// } else {
// double indicatorValue = _pulledExtent / 70.0 * 0.8;
// _indicatorValue = indicatorValue < 0.8 ? indicatorValue : 0.8;
// //
// if (_refreshState == RefreshMode.drag) {
// if (_pulledExtent >= _openSecondFloorExtent) {
// widget.secondFloorOpen.value = true;
// } else {
// widget.secondFloorOpen.value = false;
// }
// }
// }
// }
// });
// }
// @override
// Widget build(BuildContext context) {
// // var spaceWidth = SizedBox(height: ScreenUtil().screenWidth / 19);
// // return RefreshIndicator(
// // onRefresh: () async => widget.refreshCall(),
// // child: ListView(
// // children: [
// // Container(
// // constraints: BoxConstraints(
// // minHeight: 200.h,
// // maxWidth: double.infinity,
// // ),
// // child: Image.asset('assets/images/job_home_top_bgm.png', fit: BoxFit.fitWidth),
// // ),
// // SizedBox(height: 30.h),
// // SlidingData([
// // EntranceModel(title: '作业批阅', image: 'assets/images/job_home_marking.png', navigationUrl: RouterManager.jobMainListPagePath),
// // EntranceModel(
// // title: '学生历史作业',
// // image: 'assets/images/job_home_history.png',
// // navigationUrl: '${RouterManager.jobStudentGroupPath}?page=history',
// // ),
// // EntranceModel(title: '知识点点掌握', image: 'assets/images/job_home_knowledge.png', navigationUrl: RouterManager.jobKnowledgePointsPath)
// // ]),
// // spaceWidth,
// // $TermRow([
// // EntranceModel(title: '答题轨迹', image: 'assets/images/job_home_answer_record.png', navigationUrl: RouterManager.answerTrajectoryPath),
// // EntranceModel(
// // title: '优先批阅设定',
// // image: 'assets/images/job_home_youxian.png',
// // navigationUrl: '${RouterManager.jobStudentGroupPath}?page=set',
// // )
// // ], 0),
// // // spaceWidth,
// // // $TermRow([EntranceModel(title: '批阅设置', image: 'assets/images/job_home_marking_set.png', navigationUrl: '')], 0),
// // ],
// // ),
// // );
// var heightVal = _isOpen
// ? _secondFloor
// : _refreshState == RefreshMode.inactive
// ? 0.0
// : _pulledExtent;
// return AnnotatedRegion(
// value: const SystemUiOverlayStyle(
// systemNavigationBarColor: Color(0xFF000000),
// systemNavigationBarDividerColor: null,
// statusBarColor: Colors.white,
// systemNavigationBarIconBrightness: Brightness.light,
// statusBarIconBrightness: Brightness.dark,
// statusBarBrightness: Brightness.light,
// ),
// child: InkWell(
// onTap: () {
// if (_isOpen) {
// setState(() {
// _isOpen = false;
// _toggleAnimation = true;
// Future.delayed(_toggleAnimationDuration, () {
// if (mounted) {
// setState(() {
// _toggleAnimation = false;
// });
// }
// });
// });
// }
// },
// child: AnimatedContainer(
// padding: EdgeInsets.zero,
// height: heightVal,
// color: Colors.white,
// duration: _toggleAnimation ? _toggleAnimationDuration : Duration(milliseconds: 1),
// child: Stack(
// children: <Widget>[
// Positioned(
// bottom: 0.0,
// left: 0.0,
// right: 0.0,
// child: Container(
// height: MediaQuery.of(context).size.height,
// width: double.infinity,
// child: Image.asset(
// 'assets/images/job_home_top_bgm.png',
// fit: BoxFit.fitHeight,
// ),
// ),
// ),
// Positioned(
// bottom: 0.0,
// left: 0.0,
// right: 0.0,
// child: AnimatedCrossFade(
// firstChild: Center(
// child: Container(
// alignment: Alignment.center,
// margin: EdgeInsets.only(
// bottom: 20.0,
// top: 10.0,
// ),
// width: 24.0,
// height: 24.0,
// child: Offstage(
// offstage: widget.secondFloorOpen.value,
// child: CircularProgressIndicator(
// value: _indicatorValue,
// valueColor: AlwaysStoppedAnimation(Colors.white),
// strokeWidth: 2.4,
// ),
// ),
// ),
// ),
// secondChild: Center(
// child: Container(
// alignment: Alignment.center,
// margin: EdgeInsets.only(
// bottom: 20.0,
// top: 10.0,
// ),
// child: Offstage(
// offstage: !widget.secondFloorOpen.value,
// child: Text(
// '欢迎来到二楼',
// style: TextStyle(fontSize: 18.0, color: Colors.white),
// ),
// ),
// ),
// ),
// crossFadeState: widget.secondFloorOpen.value ? CrossFadeState.showSecond : CrossFadeState.showFirst,
// duration: Duration(milliseconds: 300),
// ),
// ),
// ],
// ),
// ),
// ),
// );
// }
// }
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:functional_widget_annotation/functional_widget_annotation.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/event_bus/job_home_refresh_bus.dart';
import 'package:marking_app/common/model/job/job_task_item.dart';
import 'package:marking_app/common/model/marking/marking_list_params.dart';
import 'package:marking_app/pages/common/event_bus_mixin.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/easy_refresh/MyEmptyWidget.dart';
import 'package:marking_app/utils/easy_refresh/mixin/refresh_data_handle.dart';
import 'package:marking_app/utils/index.dart';
import 'package:marking_app/utils/my_text.dart';
import 'package:badges/badges.dart' as badges;
import 'package:marking_app/utils/request/rest_client.dart';
import 'components/new_version_of_homework/homework_tasks_view_item.dart';
part 'job_home.g.dart';
class JobHome extends StatefulWidget {
const JobHome({super.key});
@override
State<JobHome> createState() => _JobHomeState();
}
class _JobHomeState extends State<JobHome>
with CommonMixin, EventBusMixin, RefreshDataHandle<JobTaskItem, MarkingListParams>, AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
var param = MarkingListParams(isFinish: false, page: 1, limit: 1, pageType: 0);
int totalJobNumber = 0;
List<JobTaskItem> jobDatas = [];
late final EasyRefreshController _refreshController;
@override
void initState() {
_refreshController = EasyRefreshController();
super.initState();
}
@override
void dispose() {
_refreshController.dispose();
eventCancel();
super.dispose();
}
/* 发起请求 => 作业 */
Future<void> toGetPageData({bool isReFresh = false}) async {
if (!isReFresh) {
param.page++;
}
RestClient client = await getClient();
BasePageData<JobTaskItem>? results = await toRefreshData(
_refreshController,
api: client.getJobsByPage,
params: param,
isReFresh: isReFresh,
context: context,
);
if (results != null) {
Future.delayed(Duration(seconds: 1), () => eventFire(model: QuantityToBeReviewedData(results.total)));
if (isReFresh) {
jobDatas.clear();
jobDatas = results.items;
} else
jobDatas.addAll(results.items);
setState(() {});
}
}
@override
Widget build(BuildContext context) {
super.build(context);
return AnnotatedRegion(
value: const SystemUiOverlayStyle(
systemNavigationBarColor: Color(0xFF000000),
systemNavigationBarDividerColor: null,
statusBarColor: Colors.white,
systemNavigationBarIconBrightness: Brightness.light,
statusBarIconBrightness: Brightness.dark,
statusBarBrightness: Brightness.light,
),
child: EasyRefresh(
firstRefresh: true,
taskIndependence: true,
enableControlFinishLoad: true,
enableControlFinishRefresh: true,
emptyWidget: jobDatas.isEmpty ? $TheJobMainBox(emptyWidget: MyEmptyWidget()) : null,
controller: _refreshController,
header: MaterialHeader(),
footer: TaurusFooter(),
child: ListView(
children: [
// Container(
// constraints: BoxConstraints(
// minHeight: 200.h,
// maxWidth: double.infinity,
// ),
// // decoration: BoxDecoration(
// // image: DecorationImage(
// // image: AssetImage('assets/images/job_home_top_bgm.png'),
// // fit: BoxFit.fitWidth, //
// // ),
// // ),
// child: Image.asset('assets/images/job_home_top_bgm.png', fit: BoxFit.fitWidth),
// ),
$TheJobMainBox(),
// spaceWidth,
// $TermRow([EntranceModel(title: '批阅设置', image: 'assets/images/job_home_marking_set.png', navigationUrl: '')], 0),
Container(
padding: EdgeInsets.symmetric(horizontal: 12.w),
child: Column(
children: jobDatas
.map((e) => HomeworkTasksViewItem(completed: false, jobTaskItem: e, call: () => _refreshController.callRefresh()))
.toList(),
),
)
],
),
onRefresh: () => toGetPageData(isReFresh: true),
onLoad: () => toGetPageData(isReFresh: false),
),
);
}
}
class EntranceModel extends Object {
String title;
String image;
String navigationUrl;
EntranceModel({required this.title, required this.image, required this.navigationUrl});
}
class QuantityToBeReviewedData extends Object {
int num;
QuantityToBeReviewedData(this.num);
}
@swidget
Widget $termRow(BuildContext context, List<EntranceModel> items, int data) {
var leng = items.length;
Widget childWidget;
switch (leng) {
case 1:
childWidget = Row(children: [Expanded(child: $TermItem(items[0], data))]);
break;
case 2:
childWidget = Row(children: [
Expanded(flex: 9, child: $TermItem(items[0], data)),
Expanded(flex: 1, child: SizedBox()),
Expanded(flex: 9, child: $TermItem(items[1], data)),
]);
break;
case 3:
double _theHeight = ScreenUtil().screenWidth / 19 + 54.h * 2;
childWidget = Row(
children: [
Expanded(child: $TermItem(items[0], data, theHeight: _theHeight)),
SizedBox(width: ScreenUtil().screenWidth / 19),
Expanded(
child: SizedBox(
height: _theHeight,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
$TermItem(items[1], data),
$TermItem(items[2], data),
],
),
),
),
],
);
break;
default:
childWidget = Container();
}
return Container(padding: EdgeInsets.symmetric(horizontal: 14.w), child: childWidget);
}
@swidget
Widget $termItem(BuildContext context, EntranceModel e, int data, {double? theHeight}) {
bool isJob = e.title == '作业批阅';
return Material(
color: Colors.white,
elevation: 3.r,
shadowColor: const Color.fromRGBO(231, 231, 231, 1),
borderRadius: BorderRadius.all(Radius.circular(8.r)),
child: InkWell(
onTap: () => easyThrottle('GO_TO_JOB_HOME_NAVIGATION', () {
RouterManager.router.navigateTo(context, e.navigationUrl, transition: getTransition());
}),
// splashColor: splashColor,
borderRadius: BorderRadius.all(Radius.circular(8.r)),
child: badges.Badge(
showBadge: isJob && data > 0,
ignorePointer: false,
badgeContent: quickText(data, color: Colors.white, size: 10.sp),
badgeAnimation: badges.BadgeAnimation.rotation(
animationDuration: Duration(seconds: 1),
colorChangeAnimationDuration: Duration(seconds: 1),
loopAnimation: false,
curve: Curves.fastOutSlowIn,
colorChangeAnimationCurve: Curves.easeInCubic,
),
badgeStyle: badges.BadgeStyle(
badgeColor: Color.fromRGBO(255, 105, 105, 1),
shape: badges.BadgeShape.square,
borderRadius: BorderRadius.only(topLeft: Radius.circular(10.r), topRight: Radius.circular(8.5.r), bottomRight: Radius.circular(8.5.r)),
// borderSide: BorderSide(color: Colors.white, width: 2),
elevation: 1,
padding: EdgeInsets.symmetric(horizontal: isPad() ? 11.w : 16.w, vertical: 2.h),
),
position: badges.BadgePosition.topEnd(top: 10.r, end: 10.r),
child: Container(
height: theHeight,
padding: EdgeInsets.symmetric(vertical: 12.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(8.r)),
// boxShadow: [
// BoxShadow(
// color: const Color.fromRGBO(231, 231, 231, 1),
// offset: Offset(4.w, 6.h), //y轴偏移量
// blurRadius: 8, //
// spreadRadius: 0.2, //
// )
// ],
// border: Border.all(width: 0.5.w, color: Color.fromARGB(255, 219, 226, 250)),
),
alignment: Alignment.center,
child: isJob
? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(e.image, height: 32.r, width: 32.r, fit: BoxFit.cover),
SizedBox(height: 6.r),
quickText(e.title, size: 12.sp, color: Color.fromRGBO(79, 79, 79, 1), fontWeight: FontWeight.w500),
],
)
: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(e.image, height: 32.r, width: 32.r, fit: BoxFit.cover),
SizedBox(width: 6.r),
quickText(e.title, size: 12.sp, color: Color.fromRGBO(79, 79, 79, 1), fontWeight: FontWeight.w500),
],
),
),
)),
);
}
class SlidingData extends HookWidget with EventBusMixin {
final List<EntranceModel> items;
SlidingData(this.items);
@override
Widget build(BuildContext context) {
var dataNumber = useState<QuantityToBeReviewedData?>(null);
useEffect(() {
eventOn(callback: (QuantityToBeReviewedData data) => (dataNumber.value = data));
return () {
eventCancel();
};
}, []);
return $TermRow(items, dataNumber.value?.num ?? 0);
}
}
//
@swidget
Widget $theJobMainBox(BuildContext context, {Widget? emptyWidget}) {
var spaceWidth = SizedBox(height: ScreenUtil().screenWidth / 19);
return Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(height: MediaQuery.of(context).padding.top + 20.h),
SlidingData([
EntranceModel(title: '作业批阅', image: 'assets/images/job_home_marking.png', navigationUrl: RouterManager.jobMainListPagePath),
EntranceModel(
title: '学生历史作业',
image: 'assets/images/job_home_history.png',
navigationUrl: '${RouterManager.jobStudentGroupPath}?page=history',
),
EntranceModel(title: '知识点点掌握', image: 'assets/images/job_home_knowledge.png', navigationUrl: RouterManager.jobKnowledgePointsPath)
]),
spaceWidth,
$TermRow([
EntranceModel(title: '答题轨迹', image: 'assets/images/job_home_answer_record.png', navigationUrl: RouterManager.answerTrajectoryPath),
EntranceModel(
title: '优先批阅设定',
image: 'assets/images/job_home_youxian.png',
navigationUrl: '${RouterManager.jobStudentGroupPath}?page=set',
)
], 0),
if (emptyWidget != null) emptyWidget,
spaceWidth,
],
);
}

View File

@ -0,0 +1,486 @@
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:functional_widget_annotation/functional_widget_annotation.dart';
import 'package:marking_app/common/mixin/common.dart';
import 'package:marking_app/common/model/common/base_structure_result.dart';
import 'package:marking_app/common/model/job/job_knowledge_points.dart';
import 'package:marking_app/common/model/job/job_student_history.dart';
import 'package:marking_app/components/ReturnToHomepage.dart';
import 'package:marking_app/pages/homework_correction/widget/personal_detail_topbar.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/easy_refresh/MyEmptyWidget.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:percent_indicator/percent_indicator.dart';
import 'package:syncfusion_flutter_datepicker/datepicker.dart';
part 'job_knowledge_points.g.dart';
class JobKnowledgePoints extends StatefulWidget {
const JobKnowledgePoints({Key? key,}) : super(key: key);
@override
_JobKnowledgePointsState createState() => _JobKnowledgePointsState();
}
class _JobKnowledgePointsState extends State<JobKnowledgePoints> with CommonMixin, TickerProviderStateMixin {
@override
int page = 1;
int pageSize = 10;
int totalPages = 0;
late TabController tabController;
String startDataTime = CommonUtils.getWeekStartDate().toString().substring(0, 10);
String endDataTime = CommonUtils.getWeekEndDate().toString().substring(0, 10);
String customTimeStr = '自定义';
List<KnowledgePoints> dataList = [];
late final EasyRefreshController refreshController;
//
late final TextEditingController textController;
int studentId = 0;
@override
void initState() {
super.initState();
textController = TextEditingController();
refreshController = EasyRefreshController();
tabController = TabController(length: 3, vsync: this);
EasyLoading.show(status: 'loading...');
getList();
}
@override
void dispose() {
super.dispose();
tabController.dispose();
textController.dispose();
}
void getList() async {
/* print('startDataTime=$startDataTime');
print('endDataTime=$endDataTime');*/
RestClient _client = await getClient();
BaseStructureResult<List<KnowledgePoints>> res =
await _client.getKnowledgeReport(startDataTime,endDataTime,textController.text);
if (res.success) {
setState(() {
if (page == 1) {
dataList = res.data!;
} else {
dataList = [...dataList, ...res.data!];
}
// totalPages = res.data!.pagedList.totalPages;
});
}
EasyLoading.dismiss();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color.fromRGBO(245, 245, 245, 1),
appBar: AppBar(
backgroundColor: Colors.white,
title: Text('知识点掌握', style: TextStyle(fontSize: 14.sp, color: Color(0xFF333333))),
centerTitle: true,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios, color: Colors.black),
onPressed: () => Navigator.of(context).pop(),
),
actions: [
ReturnToHomepage(),
],
elevation: 0,
),
body: Column(
children: [
Container(
margin: EdgeInsets.all(15.r),
height: 30.r,
child: Row(
children: [
Expanded(
child: Container(
padding: EdgeInsets.only(left: 10.r,right: 10.r),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.r),
border: Border.all(width: 1.r,color: Color(0xFFDDDDDD)),
color: Colors.white,
),
child: TextField(
controller: textController,
textInputAction: TextInputAction.next,
style: TextStyle(
color: const Color.fromRGBO(80, 87, 103, 1),
fontSize: 10.sp,
),
decoration: InputDecoration(
hintText: "请输入知识点名称",
hintStyle: TextStyle(fontSize: 10.sp, color: const Color.fromRGBO(153, 153, 153, 1)),
labelStyle: TextStyle(fontSize: 10.sp, color: const Color.fromRGBO(148, 163, 182, 1)),
border: InputBorder.none,
),
),
),
),
SizedBox(width: 10.r,),
InkWell(
onTap: (){
page = 1;
setState(() {});
getList();
},
child: Container(
width: 50.r,
height: 30.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
color: Color(0xFF6888FD),
),
child:Center(
child: Text('查询',style: TextStyle(fontSize: 12.sp,color: Colors.white),),
),
),
)
],
),
),
jobConditionFilter(context,
controller: tabController,
customTimeStr: customTimeStr,
customTime: tabController.index != 3 ||
((endDataTime == null || endDataTime == '') && (startDataTime == null || startDataTime == ''))
? null
: PickerDateRange(
startDataTime == null || startDataTime == '' ? null : DateTime.parse(startDataTime!),
endDataTime == null || endDataTime == '' ? null : DateTime.parse(endDataTime!),
), onTimeFilter: (String? startTime, String? endTime) {
EasyLoading.show(status: 'loading...');
if (startTime == null && endTime == null) {
if (tabController.index == 3) {
tabController.animateTo(0);
}
startDataTime = '';
endDataTime = '';
customTimeStr = '自定义';
} else {
startDataTime = startTime != null ? startTime : '';
endDataTime = endTime != null ? endTime : '';
}
page = 1;
setState(() {});
getList();
// _refreshController2.callRefresh();
}, refreshTime: (value) {
if (value != null && value.startDate != null) {
customTimeStr = value.startDate?.toString().substring(0, 10) ?? '';
setState(() {});
if (value.endDate != null) {
if (!isPad() && value.startDate!.year == value.endDate!.year) {
customTimeStr =
value.startDate.toString().substring(5, 10) + '~${value.endDate.toString().substring(5, 10)}';
setState(() {});
} else {
customTimeStr = '$customTimeStr~${value.endDate?.toString().substring(0, 10)}';
setState(() {});
}
}
}
}),
Expanded(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 10.r),
child: EasyRefresh(
firstRefresh: false,
taskIndependence: true,
controller: refreshController,
header: MaterialHeader(),
footer: TaurusFooter(),
onRefresh: () async {
setState(() {
page = 1;
});
getList();
},
onLoad: () async {
if (page < totalPages) {
setState(() {
page += 1;
});
getList();
}
},
child: dataList.length > 0
? ListView.builder(
itemCount: dataList.length,
itemBuilder: (context, index) {
KnowledgePoints item = dataList[index];
return InkWell(
onTap: () {
RouterManager.router.navigateTo(
context,
RouterManager.jobKnowledgePointsDetailPath +
'?knowledgeName=${Uri.encodeComponent(item.knowledgeName)}&knowledgeId=${item.knowledgeId}',
transition: getTransition(),
);
},
child: Container(
margin: EdgeInsets.symmetric(vertical: 5.r, horizontal: 14.r),
padding: EdgeInsets.symmetric(vertical: 14.r, horizontal: 10.r),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10.r)),
color: Colors.white),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: Text(
item.knowledgeName,
style: TextStyle(fontSize: 14.sp, color: Color(0xFF505050)),
)),
Container(
width: 49.r,
height: 22.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20.r)),
border: Border.all(width: 1.r, color: Color(0xFF6888FD)),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'${item.count}',
style: TextStyle(fontSize: 10.sp, color: Color(0xFF6888FD)),
),
Image.asset('assets/images/right_icon_blue.png',width: 8.r,height: 8.r,),
],
),
),
],
),
SizedBox(height: 10.r,),
progressBar(context,
title: '正确率:',
color: Color(0xFF90E0BE),
percent: item.correctRate / 100,
padingEdg: EdgeInsets.zero,
marginEdg: EdgeInsets.only(top: 8.h)),
],
),
),
);
})
: MyEmptyWidget(),
),
),
),
],
),
);
}
}
@swidget
Widget progressBar(
BuildContext context, {
double? fontSize,
double? lineHeight,
required String title,
required Color color,
required double percent,
required EdgeInsets padingEdg,
required EdgeInsets marginEdg,
}) {
var percentStr = '${doubleToStringAsFixed(percent * 100)}%';
fontSize ??= 10.sp;
lineHeight ??= 8.h;
return Container(
margin: marginEdg,
padding: padingEdg,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
quickText(title, color: Color(0xFF8B8B8B), size: fontSize),
Expanded(
flex: 1,
child: Container(
child: Row(
children: [
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.r),
/* boxShadow: [
BoxShadow(
color: color,
spreadRadius: 0.6,
blurRadius: 3,
offset: Offset(0, 0),
),
],*/
),
child: LinearPercentIndicator(
padding: EdgeInsets.zero,
animation: true,
lineHeight: lineHeight,
animationDuration: 2500,
percent: percent,
/* center: Text(
percentStr,
style: TextStyle(color: Colors.white, fontSize: 4.5.sp),
),*/
// linearStrokeCap: LinearStrokeCap.butt,
progressColor: color,
backgroundColor: Color(0xFFE8E8E8),
barRadius: Radius.circular(10.r),
// linearGradient: LinearGradient(
// tileMode: TileMode.mirror,
// stops: [0.0, 1.0],
// colors: [color.withOpacity(0.1), color],
// ),
),
),
),
SizedBox(width: 4.w),
quickText(percentStr, size: fontSize, color: Color(0xFF606060))
],
),
),
),
],
),
);
}
///
@hwidget
Widget jobConditionFilter(BuildContext context,
{required TabController controller,
PickerDateRange? customTime,
required Function refreshTime,
required String customTimeStr,
required Function(String? startTime, String? endTime) onTimeFilter}) {
var customTimeState = PickerDateRange(null, null);
if (customTime != null) {
customTimeState = PickerDateRange(customTime!.startDate != null ? customTime!.startDate : null,
customTime!.endDate != null ? customTime!.endDate : null);
}
DateTime getMonthStartDate() {
DateTime now = DateTime.now();
return DateTime(now.year, now.month, 1); //
}
DateTime getMonthEndDate() {
DateTime now = DateTime.now();
int nextMonth = now.month + 1;
if (nextMonth > 12) {
nextMonth = 1;
now = now.add(Duration(days: 31 - now.day)); //
} else {
now = now.add(Duration(days: DateTime(now.year, nextMonth, 0).day - now.day)); //
}
return now;
}
return Container(
// height: 39.h,
// padding: EdgeInsets.only(left: 4.w, right: 12.w),
decoration: BoxDecoration(
color: Color.fromRGBO(244, 244, 244, 1),
// border: Border(bottom: BorderSide(color: Color.fromRGBO(204, 204, 204, 1), width: 1)),
),
child: Container(
alignment: Alignment.centerLeft,
decoration: BoxDecoration(
border: Border(bottom: BorderSide(width: 1.r,color: Color(0xFFCCCCCC)))
),
child: TabBar(
controller: controller,
unselectedLabelStyle: TextStyle(fontSize: 12.sp, color: const Color.fromRGBO(102, 102, 102, 1)),
labelStyle: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(116, 145, 253, 1),
),
isScrollable: true,
labelColor: Color(0xFF6888FD),
unselectedLabelColor: Color(0xFF666666),
padding: EdgeInsets.symmetric(horizontal: 14.r),
// indicatorSize: TabBarIndicatorSize.label, //
onTap: (int val) async {
switch (val) {
case 0: //
onTimeFilter(
CommonUtils.getWeekStartDate().toString().substring(0, 10),
CommonUtils.getWeekEndDate().toString().substring(0, 10),
);
break;
case 1: //
onTimeFilter(
getMonthStartDate().toString().substring(0, 10),
getMonthEndDate().toString().substring(0, 10),
);
break;
default: //
var dialogData = await showDialog<PickerDateRange?>(
context: context,
builder: (BuildContext context1) {
return Center(
child: Container(
color: Colors.white,
width: isPad() ? ScreenUtil().screenWidth / 2 : ScreenUtil().screenWidth / 1.3,
height: ScreenUtil().screenHeight / 2,
child: SfDateRangePicker(
showActionButtons: true,
confirmText: '确定',
cancelText: '取消',
onSubmit: (p0) {
print(p0);
Navigator.of(context1).pop(p0);
refreshTime(p0);
},
onCancel: () {
Navigator.of(context1).pop();
},
selectionMode: DateRangePickerSelectionMode.range,
initialSelectedRange: customTimeState,
),
),
);
});
// startDate: 2024-03-04 18:47:00.117958, endDate: 2024-03-11 18:47:00.117986
// if (dialogData != null && (dialogData.startDate != null || dialogData.endDate != null)) {}
onTimeFilter(
dialogData?.startDate?.toString().substring(0, 10),
dialogData?.endDate?.toString().substring(0, 10),
);
customTimeState = dialogData!;
}
},
tabs: <Widget>[
const Tab(text: '近一周'),
const Tab(text: '近一月'),
Tab(text: customTimeStr),
],
),
),
);
}

View File

@ -0,0 +1,465 @@
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:functional_widget_annotation/functional_widget_annotation.dart';
import 'package:marking_app/common/mixin/common.dart';
import 'package:marking_app/common/model/common/base_structure_result.dart';
import 'package:marking_app/common/model/job/job_knowledge_detail_student.dart';
import 'package:marking_app/common/model/job/job_knowledge_points.dart';
import 'package:marking_app/common/model/job/job_knowledge_points_detail.dart';
import 'package:marking_app/common/model/job/job_student_history.dart';
import 'package:marking_app/components/ReturnToHomepage.dart';
import 'package:marking_app/pages/homework_correction/widget/personal_detail_topbar.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/easy_refresh/MyEmptyWidget.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:percent_indicator/percent_indicator.dart';
import 'package:photo_view/photo_view.dart';
import 'package:syncfusion_flutter_datepicker/datepicker.dart';
part 'job_knowledge_points_detail.g.dart';
class JobKnowledgePointsDetail extends StatefulWidget {
final String knowledgeName;
final int knowledgeId;
const JobKnowledgePointsDetail(
{Key? key, required this.knowledgeName, required this.knowledgeId})
: super(key: key);
@override
_JobKnowledgePointsDetailState createState() =>
_JobKnowledgePointsDetailState();
}
class _JobKnowledgePointsDetailState extends State<JobKnowledgePointsDetail>
with CommonMixin, TickerProviderStateMixin {
@override
List<KnowledgePointsDetail> dataList = [];
List<JobKnowledgeDetailStudent> studentList = [];
late final EasyRefreshController refreshController;
String paperImg = '';
int studentId = 0;
@override
void initState() {
super.initState();
refreshController = EasyRefreshController();
EasyLoading.show(status: 'loading...');
getList();
}
@override
void dispose() {
super.dispose();
}
void getList() async {
RestClient _client = await getClient();
BaseStructureResult<List<KnowledgePointsDetail>> res =
await _client.getKnowledgeReportDetail(widget.knowledgeId);
if (res.success) {
setState(() {
dataList = res.data!;
});
}
EasyLoading.dismiss();
}
showStudent(questionid, title) async {
await getStudents(questionid);
showModalBottomSheet(
context: context,
elevation: 10,
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.r),
topRight: Radius.circular(20.r),
),
),
builder: (BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 2.w),
child: Column(
children: [
Container(
margin: EdgeInsets.only(top: 14.h),
child: quickText(
title,
size: 18.sp,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(60, 60, 60, 1),
),
),
Expanded(
child: ListView(
padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 4.w),
children: [
Wrap(
spacing: 6.r, // ()
runSpacing: 4.r, //
alignment: WrapAlignment.spaceAround, //沿
children: studentList.map((e) {
return Container(
padding: EdgeInsets.symmetric(
vertical: 4.r, horizontal: 8.r),
decoration: BoxDecoration(
color: e.isAnswer
? Color(0xFF4CC793)
: Color(0xFFE2E2E2),
borderRadius: BorderRadius.circular(4.r),
),
child: quickText(e.studentName,
color:
e.isAnswer ? Colors.white : Color(0xFF505E6E),
size: 10.sp),
);
}).toList(),
),
],
),
)
],
),
);
},
);
EasyLoading.dismiss();
}
showImg(int sectionId, String questionNo) async {
await getImg(sectionId, questionNo);
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
insetPadding: EdgeInsets.symmetric(vertical: 55.r,horizontal: 45.r),
contentPadding: EdgeInsets.all(0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15.r))),
content: Container(
width: MediaQuery.of(context).size.width,
// height: MediaQuery.of(context).size.height,
child: Image.network(paperImg),
),
);
},
);
EasyLoading.dismiss();
}
getStudents(questionid) async {
RestClient _client = await getClient();
BaseStructureResult<List<JobKnowledgeDetailStudent>> res =
await _client.getKnowledgeStudent(questionid);
if (res.success) {
studentList = res.data!;
} else {
studentList = [];
}
}
getImg(int sectionId, String questionNo) async {
RestClient _client = await getClient();
BaseStructureResult<String> res =
await _client.getKnowledgeImg(sectionId, questionNo);
if (res.success) {
paperImg = res.data!;
} else {
paperImg = '';
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color.fromRGBO(245, 245, 245, 1),
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(widget.knowledgeName,
style: TextStyle(fontSize: 14.sp, color: Color(0xFF333333))),
centerTitle: true,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios, color: Colors.black),
onPressed: () => Navigator.of(context).pop(),
),
actions: [
ReturnToHomepage(),
],
elevation: 0,
),
body: Padding(
padding: EdgeInsets.symmetric(vertical: 10.r),
child: EasyRefresh(
firstRefresh: false,
taskIndependence: true,
controller: refreshController,
header: MaterialHeader(),
footer: TaurusFooter(),
onRefresh: () async {
getList();
},
onLoad: () async {
// getList();
},
child: dataList.length > 0
? ListView.builder(
itemCount: dataList.length,
itemBuilder: (context, index) {
KnowledgePointsDetail item = dataList[index];
return InkWell(
onTap: () {
/* RouterManager.router.navigateTo(
context,
RouterManager.quickCheckPersonalPath +
'?jobId=${item.jobName}&studentId=$studentId',
transition: getTransition(),
);*/
},
child: Container(
margin: EdgeInsets.symmetric(
vertical: 5.r, horizontal: 14.r),
padding: EdgeInsets.symmetric(
vertical: 14.r, horizontal: 10.r),
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(10.r)),
color: Colors.white),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
item.publishTime.substring(0, 10),
style: TextStyle(
fontSize: 14.sp,
color: Color(0xFF505050)),
),
SizedBox(
width: 10.r,
),
Expanded(
child: Text(
item.jobName,
style: TextStyle(
fontSize: 14.sp,
color: Color(0xFF505050)),
)),
InkWell(
onTap: () {
EasyLoading.show(status: 'loading...');
showImg(item.sectionId, item.questionNo);
},
child: Container(
width: 49.r,
height: 22.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(20.r)),
border: Border.all(
width: 1.r, color: Color(0xFF8B8B8B)),
),
child: Center(
child: Text(
'${item.questionNo}',
style: TextStyle(
fontSize: 10.sp,
color: Color(0xFF8B8B8B)),
),
),
),
),
],
),
SizedBox(
height: 10.r,
),
Container(
margin: EdgeInsets.only(top: 8.h),
padding: EdgeInsets.zero,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: () {
EasyLoading.show(status: 'loading...');
showStudent(
item.questionId, item.jobName);
},
child: Container(
margin: EdgeInsets.only(right: 6.r),
width: 56.r,
height: 20.r,
decoration: BoxDecoration(
color: Color(0xFFD4FFED),
borderRadius:
BorderRadius.circular(20.r),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
quickText('正确率',
color: Color(0xFF4CC793),
size: 10.sp),
Image.asset('assets/images/icon_back_green.png',width: 8.r,height: 8.r,)
],
)),
),
Expanded(
flex: 1,
child: Container(
child: Row(
children: [
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(10.r),
),
child: LinearPercentIndicator(
padding: EdgeInsets.zero,
animation: true,
lineHeight: 8.h,
animationDuration: 2500,
percent: item.correctRate / 100,
progressColor:
Color(0xFF90E0BE),
backgroundColor:
Color(0xFFE8E8E8),
barRadius:
Radius.circular(10.r),
),
),
),
SizedBox(width: 4.w),
quickText(
'${doubleToStringAsFixed(item.correctRate / 100 * 100)}%',
size: 10.sp,
color: Color(0xFF606060))
],
),
),
),
],
),
),
/* progressBar(context,
title: '正确率 >',
color: Color(0xFF90E0BE),
percent: item.correctRate / 100,
padingEdg: EdgeInsets.zero,
marginEdg: EdgeInsets.only(top: 8.h),
studentCall:showStudent(item.questionId,item.jobName),
),*/
],
),
),
);
})
: MyEmptyWidget(),
),
),
);
}
}
@swidget
Widget progressBar(
BuildContext context, {
double? fontSize,
double? lineHeight,
required String title,
required Color color,
required double percent,
required EdgeInsets padingEdg,
required EdgeInsets marginEdg,
required Future<dynamic> studentCall,
}) {
var percentStr = '${doubleToStringAsFixed(percent * 100)}%';
fontSize ??= 10.sp;
lineHeight ??= 8.h;
return Container(
margin: marginEdg,
padding: padingEdg,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: () {
studentCall;
},
child: Container(
margin: EdgeInsets.only(right: 6.r),
width: 56.r,
height: 20.r,
decoration: BoxDecoration(
color: Color(0xFFD4FFED),
borderRadius: BorderRadius.circular(20.r),
),
child: Center(
child: quickText(title,
color: Color(0xFF4CC793), size: fontSize))),
),
Expanded(
flex: 1,
child: Container(
child: Row(
children: [
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.r),
/* boxShadow: [
BoxShadow(
color: color,
spreadRadius: 0.6,
blurRadius: 3,
offset: Offset(0, 0),
),
],*/
),
child: LinearPercentIndicator(
padding: EdgeInsets.zero,
animation: true,
lineHeight: lineHeight,
animationDuration: 2500,
percent: percent,
/* center: Text(
percentStr,
style: TextStyle(color: Colors.white, fontSize: 4.5.sp),
),*/
// linearStrokeCap: LinearStrokeCap.butt,
progressColor: color,
backgroundColor: Color(0xFFE8E8E8),
barRadius: Radius.circular(10.r),
// linearGradient: LinearGradient(
// tileMode: TileMode.mirror,
// stops: [0.0, 1.0],
// colors: [color.withOpacity(0.1), color],
// ),
),
),
),
SizedBox(width: 4.w),
quickText(percentStr, size: fontSize, color: Color(0xFF606060))
],
),
),
),
],
),
);
}

View File

@ -60,6 +60,7 @@ class _JobPersonalDetailState extends State<JobPersonalDetail> with CommonMixin,
}
void getList() async {
print(widget.studentId);
RestClient _client = await getClient();
BaseStructureResult<JobStudentHistory> res =
await _client.getStudentJobHistory(widget.studentId, !isJob, startDataTime, endDataTime, page, pageSize);

View File

@ -16,8 +16,9 @@ import 'package:marking_app/utils/request/rest_client.dart';
class JobPriorityReviewSet extends StatefulWidget {
final String groupId;
final String title;
final String? page;
const JobPriorityReviewSet({Key? key, required this.groupId,required this.title})
const JobPriorityReviewSet({Key? key, required this.groupId,required this.title,this.page = ''})
: super(key: key);
@override
@ -207,8 +208,27 @@ class _JobPriorityReviewSetState extends State<JobPriorityReviewSet>
fontSize: 12.sp,
color: Color(0xFF6888FD)),
)),
item.readLevel == 1
? InkWell(
widget.page == 'answerTrajectory'?Container(
height: 20.r,
width: 70.r,
decoration: BoxDecoration(
border: Border.all(width: 1.r,color: Color(0xFFFFA41E)),
borderRadius: BorderRadius.all(Radius.circular(20.r)),
),
child: Center(child: Text('详情',style: TextStyle(fontSize: 10.r,color: Color(0xFFFFA41E))),
)):widget.page == 'history'?Container(
height: 20.r,
width: 70.r,
decoration: BoxDecoration(
color: Color(0xFF6888FD),
borderRadius: BorderRadius.all(Radius.circular(20.r))
),
child: Center(child: Text('历史作业',style: TextStyle(fontSize: 10.r,color: Colors.white),)),
): item.readLevel == 1
?
InkWell(
onTap: () {
setState(() {
isClicking = true;
@ -218,7 +238,7 @@ class _JobPriorityReviewSetState extends State<JobPriorityReviewSet>
EasyLoading.show(
status: 'loading...');
},
child: Container(
child:Container(
height: 20.r,
width: 70.r,
decoration: BoxDecoration(
@ -246,7 +266,7 @@ class _JobPriorityReviewSetState extends State<JobPriorityReviewSet>
),
),
)
: InkWell(
:InkWell(
onTap: () {
setState(() {
isClicking = true;
@ -256,7 +276,7 @@ class _JobPriorityReviewSetState extends State<JobPriorityReviewSet>
EasyLoading.show(
status: 'loading...');
},
child: Container(
child: Container(
height: 20.r,
width: 70.r,
decoration: BoxDecoration(
@ -284,34 +304,6 @@ class _JobPriorityReviewSetState extends State<JobPriorityReviewSet>
),
),
),
/* SizedBox(
width: 5.r,
),
InkWell(
onTap: () {
RouterManager.router.navigateTo(context,
'${RouterManager.jobPersonalDetailPath}?studentId=${item.studentId}&studentName=${Uri.encodeComponent(item.studentName)}');
},
child: Container(
height: 20.r,
width: 70.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(20.r)),
color: Colors.white,
border: Border.all(
width: 1.r,
color: Color(0xFFFCA017))),
child: Center(
child: Text(
'详情',
style: TextStyle(
fontSize: 10.sp,
color: Color(0xFFFCA017)),
),
),
),
)*/
],
),
),
@ -346,7 +338,24 @@ class _JobPriorityReviewSetState extends State<JobPriorityReviewSet>
fontSize: 12.sp,
color: Color(0xFF6888FD)),
)),
item.readLevel == 1
widget.page == 'answerTrajectory'?Container(
height: 24.r,
width: 72.r,
decoration: BoxDecoration(
border: Border.all(width: 1.r,color: Color(0xFFFFA41E)),
borderRadius: BorderRadius.all(Radius.circular(20.r)),
),
child: Center(child: Text('详情',style: TextStyle(fontSize: 10.r,color: Color(0xFFFFA41E))),
)):widget.page == 'history'?Container(
height: 24.r,
width: 82.r,
decoration: BoxDecoration(
color: Color(0xFF6888FD),
borderRadius: BorderRadius.all(Radius.circular(20.r))
),
child: Center(child: Text('历史作业',style: TextStyle(fontSize: 10.r,color: Colors.white),)),
):item.readLevel == 1
? InkWell(
onTap: () {
setState(() {
@ -420,34 +429,6 @@ class _JobPriorityReviewSetState extends State<JobPriorityReviewSet>
),
),
),
/* SizedBox(
width: 5.r,
),
InkWell(
onTap: () {
RouterManager.router.navigateTo(context,
'${RouterManager.jobPersonalDetailPath}?studentId=${item.studentId}&studentName=${Uri.encodeComponent(item.studentName)}');
},
child: Container(
height: 20.r,
width: 70.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(20.r)),
color: Colors.white,
border: Border.all(
width: 1.r,
color: Color(0xFFFCA017))),
child: Center(
child: Text(
'详情',
style: TextStyle(
fontSize: 10.sp,
color: Color(0xFFFCA017)),
),
),
),
)*/
],
),
),

View File

@ -9,6 +9,7 @@ import 'package:marking_app/common/model/job/job_report_join_class.dart';
import 'package:marking_app/common/model/job/job_report_knowledge_model.dart';
import 'package:marking_app/common/model/job/job_report_model.dart';
import 'package:marking_app/components/ReturnToHomepage.dart';
import 'package:marking_app/pages/homework_correction/components/imgDialog.dart';
import 'package:marking_app/pages/homework_correction/widget/report_table.dart';
import 'package:marking_app/pages/homework_correction/widget/top_count.dart';
import 'package:marking_app/pages/mainPage.dart';
@ -1445,7 +1446,7 @@ Widget $unitTimeAnsweringSituation(BuildContext context, int jobid, List<Questio
// return;
// }
if (_qpm.questionPicture == null) return ToastUtils.showInfo('当前试题没有原题');
Navigator.push(
/* Navigator.push(
context,
MaterialPageRoute(builder: (_) {
return Scaffold(
@ -1453,7 +1454,8 @@ Widget $unitTimeAnsweringSituation(BuildContext context, int jobid, List<Questio
body: PhotoView(imageProvider: NetworkImage(_qpm.questionPicture!)),
);
}),
);
);*/
ImageDialog.showImgDialog(context,_qpm.questionPicture!);
},
child: Row(
mainAxisSize: MainAxisSize.min,

View File

@ -16,7 +16,8 @@ import 'package:marking_app/utils/index.dart';
import 'package:marking_app/utils/request/rest_client.dart';
class JobStudentGroup extends StatefulWidget {
const JobStudentGroup({Key? key}) : super(key: key);
final String page;
const JobStudentGroup({Key? key,required this.page}) : super(key: key);
@override
State<JobStudentGroup> createState() => _JobStudentGroupState();
@ -59,7 +60,7 @@ class _JobStudentGroupState extends State<JobStudentGroup> with CommonMixin {
}
void goNextPage(id,title){
RouterManager.router.navigateTo(context, '${RouterManager.jobPriorityReviewSetPath}?&groupId=$id&title=${Uri.encodeComponent(title)}',transition: getTransition());
RouterManager.router.navigateTo(context, '${RouterManager.jobPriorityReviewSetPath}?&groupId=$id&title=${Uri.encodeComponent(title)}&page=${widget.page}',transition: getTransition());
}
@override

View File

@ -0,0 +1,30 @@
/// 稿
//
import 'package:marking_app/common/model/job/gesture_recording.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:marking_app/common/mixin/common.dart';
final jobHandwritingDrawingTrajectoryProvider =
StateNotifierProvider<JobHandwritingDrawingTrajectoryProviderHandle, List<GestureHandwritingRecording>>(
(ref) => JobHandwritingDrawingTrajectoryProviderHandle([]));
class JobHandwritingDrawingTrajectoryProviderHandle extends StateNotifier<List<GestureHandwritingRecording>> with CommonMixin {
JobHandwritingDrawingTrajectoryProviderHandle(List<GestureHandwritingRecording> progress) : super(progress);
setVal(List<GestureHandwritingRecording> val) {
state = val;
}
}
// 稿
final jobHandwritingStudentManuscriptProvider = StateNotifierProvider<JobHandwritingStudentManuscriptHandle, ShowStudentMmanuscript>(
(ref) => JobHandwritingStudentManuscriptHandle(ShowStudentMmanuscript(true)));
class JobHandwritingStudentManuscriptHandle extends StateNotifier<ShowStudentMmanuscript> {
JobHandwritingStudentManuscriptHandle(ShowStudentMmanuscript progress) : super(progress);
setVal(ShowStudentMmanuscript val) {
state = val;
}
}

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:marking_app/common/mixin/common.dart';
import 'package:marking_app/common/model/common/base_structure_result.dart';
import 'package:marking_app/common/model/job/job_data_report.dart';
@ -8,24 +9,23 @@ import 'package:marking_app/components/ReturnToHomepage.dart';
import 'package:marking_app/pages/homework_correction/widget/student_kg_table.dart';
import 'package:marking_app/pages/homework_correction/widget/student_zg_table.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/common_utils.dart';
import 'package:marking_app/utils/request/rest_client.dart';
import 'package:marking_app/utils/toast_utils.dart';
class QuickCheckPersonal extends StatefulWidget {
import 'providers/handwriting_drawing_trajectory_provider.dart';
import 'widget/answer_handwriting.dart';
class QuickCheckPersonal extends StatefulHookConsumerWidget {
final int jobId;
final int studentId;
const QuickCheckPersonal(
{Key? key, required this.jobId, required this.studentId})
: super(key: key);
const QuickCheckPersonal({Key? key, required this.jobId, required this.studentId}) : super(key: key);
@override
State<QuickCheckPersonal> createState() => _QuickCheckPersonalState();
ConsumerState<QuickCheckPersonal> createState() => _QuickCheckPersonalState();
}
class _QuickCheckPersonalState extends State<QuickCheckPersonal>
with CommonMixin {
class _QuickCheckPersonalState extends ConsumerState<QuickCheckPersonal> with CommonMixin {
StudentDetails? studentInfo;
void initState() {
@ -40,18 +40,16 @@ class _QuickCheckPersonalState extends State<QuickCheckPersonal>
params['jobid'] = widget.jobId;
// params['jobid'] = '521646983660101';
params['studentId'] = widget.studentId;
BaseStructureResult<StudentDetails?> data =
await _client.getJobPersonalReport(params);
if(data.data!.studentId != null){
BaseStructureResult<StudentDetails?> data = await _client.getJobPersonalReport(params);
if (data.data!.studentId != null) {
setState(() {
studentInfo = data.data;
});
}else{
} else {
Navigator.pop(context);
ToastUtils.showError('暂无数据');
}
EasyLoading.dismiss();
}
@override
@ -74,7 +72,7 @@ class _QuickCheckPersonalState extends State<QuickCheckPersonal>
),
actions: [
ReturnToHomepage(),
/* Title(
/* Title(
color: Color(0xFF6888FD),
child: Container(
child: InkWell(
@ -89,20 +87,19 @@ class _QuickCheckPersonalState extends State<QuickCheckPersonal>
alignment: Alignment.center,
),
),*/
],
),
body: SingleChildScrollView(
child: Column(
children: [
Padding(
padding: EdgeInsets.only(top: 14.r,left: 14.r),
padding: EdgeInsets.only(top: 14.r, left: 14.r),
child: Row(
children: [
InkWell(
onTap: (){
RouterManager.router.navigateTo(context, '${RouterManager.jobPersonalDetailPath}?studentId=${widget.studentId}&studentName=${Uri.encodeComponent(studentInfo!.studentName!)}');
onTap: () {
RouterManager.router.navigateTo(context,
'${RouterManager.jobPersonalDetailPath}?studentId=${widget.studentId}&studentName=${Uri.encodeComponent(studentInfo!.studentName!)}');
},
child: Container(
width: 93.r,
@ -112,22 +109,37 @@ class _QuickCheckPersonalState extends State<QuickCheckPersonal>
borderRadius: BorderRadius.circular(4.r),
),
child: Center(
child: Text('历史查询',style: TextStyle(fontSize: 10.r,color: Color(0xFF2080F7)),),
child: Text(
'历史作业',
style: TextStyle(fontSize: 10.r, color: Color(0xFF2080F7)),
),
),
),
),
SizedBox(width: 10.r,),
/*Container(
width: 93.r,
height: 28.r,
decoration: BoxDecoration(
color: Color(0xFFEDFFF7),
borderRadius: BorderRadius.circular(4.r),
SizedBox(
width: 10.r,
),
InkWell(
onTap: () {
showAnswerHandwriting(context, jobId: widget.jobId, studentId: widget.studentId).then((value) {
ref.read(jobHandwritingDrawingTrajectoryProvider.notifier).setVal([]);
});
},
child: Container(
width: 93.r,
height: 28.r,
decoration: BoxDecoration(
color: Color(0xFFEDFFF7),
borderRadius: BorderRadius.circular(4.r),
),
child: Center(
child: Text(
'原稿笔迹',
style: TextStyle(fontSize: 10.r, color: Color(0xFF4CC793)),
),
),
),
child: Center(
child: Text('原稿笔迹',style: TextStyle(fontSize: 10.r,color: Color(0xFF4CC793)),),
),
),*/
),
],
),
),
@ -147,31 +159,38 @@ class _QuickCheckPersonalState extends State<QuickCheckPersonal>
children: [
Text(
'客观题',
style: TextStyle(
fontSize: 14.sp, color: Color(0xFF5C5C5C),fontWeight: FontWeight.w600),
style: TextStyle(fontSize: 14.sp, color: Color(0xFF5C5C5C), fontWeight: FontWeight.w600),
),
SizedBox(
width: 10.r,
),
Text(
'${studentInfo!.kgValidRate}%',
style: TextStyle(
fontSize: 14.sp, color: Color(0xFF6888FD),fontWeight: FontWeight.w600),
style: TextStyle(fontSize: 14.sp, color: Color(0xFF6888FD), fontWeight: FontWeight.w600),
),
],
),
SizedBox(height: 10.r,),
SizedBox(
height: studentInfo!.kgDetails.length>8?300.r:studentInfo!.kgDetails.length * 40.r + 40.r,
height: 10.r,
),
SizedBox(
height: studentInfo!.kgDetails.length > 8 ? 300.r : studentInfo!.kgDetails.length * 40.r + 40.r,
child: StudentKgTable(
headList: ['题号', '学生答案', '标准答案'],
bodyList: studentInfo!.kgDetails,
questionNumCall: (no) {
showAnswerHandwriting(context, jobId: widget.jobId, studentId: widget.studentId, questionNo: int.parse(no)).then((value) {
ref.read(jobHandwritingDrawingTrajectoryProvider.notifier).setVal([]);
});
},
),
)
],
),
),
SizedBox(height: 15.r,),
SizedBox(
height: 15.r,
),
//
Container(
padding: EdgeInsets.symmetric(vertical: 14.r, horizontal: 10.r),
@ -188,25 +207,30 @@ class _QuickCheckPersonalState extends State<QuickCheckPersonal>
children: [
Text(
'主观题',
style: TextStyle(
fontSize: 14.sp, color: Color(0xFF5C5C5C),fontWeight: FontWeight.w600),
style: TextStyle(fontSize: 14.sp, color: Color(0xFF5C5C5C), fontWeight: FontWeight.w600),
),
SizedBox(
width: 10.r,
),
Text(
'${studentInfo!.zgValidRate}%',
style: TextStyle(
fontSize: 14.sp, color: Color(0xFF6888FD),fontWeight: FontWeight.w600),
style: TextStyle(fontSize: 14.sp, color: Color(0xFF6888FD), fontWeight: FontWeight.w600),
),
],
),
SizedBox(height: 10.r,),
SizedBox(
height: studentInfo!.zgDetails.length>8?300.r:studentInfo!.zgDetails.length * 40.r + 40.r,
height: 10.r,
),
SizedBox(
height: studentInfo!.zgDetails.length > 8 ? 300.r : studentInfo!.zgDetails.length * 40.r + 40.r,
child: StudentZgTable(
headList: ['题号', '用时', '学生答案','批注结果','批注'],
headList: ['题号', '用时', '学生答案', '批注结果', '批注'],
bodyList: studentInfo!.zgDetails,
questionNumCall: (no) {
showAnswerHandwriting(context, jobId: widget.jobId, studentId: widget.studentId, questionNo: int.parse(no)).then((value) {
ref.read(jobHandwritingDrawingTrajectoryProvider.notifier).setVal([]);
});
},
),
)
],

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,286 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:marking_app/common/model/job/job_task_item.dart';
import 'package:marking_app/utils/easy_refresh/MyEmptyWidget.dart';
import 'package:marking_app/utils/index.dart';
import 'package:marking_app/utils/my_text.dart';
import '../../../routes/RouterManager.dart';
class AnswerTrajectoryJob extends StatelessWidget {
final List<JobTaskItem> jobList;
const AnswerTrajectoryJob(this.jobList, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return jobList != null && jobList.length > 0
? isPad()
? GridView(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, //widget
mainAxisSpacing: 10.h,
crossAxisSpacing: 6.w,
childAspectRatio: 2.4 //1widget
),
children: List.generate(jobList.length, (index) {
JobTaskItem item = jobList[index];
return InkWell(
onTap: (){
RouterManager.router.navigateTo(context,
'${RouterManager.answerTrajectoryJobDetailPath}?&jobId=${item.id}&jobName=${Uri.encodeComponent(item.title)}&genderName=${Uri.encodeComponent(item.genderName)}',
transition: getTransition());
},
child: Container(
padding: EdgeInsets.only(top: 10.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.r),
color: Colors.white,
boxShadow: [
BoxShadow(
color: const Color.fromRGBO(210, 216, 241, 1),
offset: Offset.zero, //y轴偏移量
blurRadius: 5.8, //
spreadRadius: 0, //
)
],
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//
Padding(
padding: EdgeInsets.symmetric(horizontal: 6.w),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 32.w,
height: 18.h,
alignment: Alignment.center,
padding: EdgeInsets.only(left: 2.w),
decoration: BoxDecoration(
color: const Color.fromRGBO(104, 136, 253, 1),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(14.r),
topRight: Radius.circular(3.r),
bottomLeft: Radius.circular(4.r),
bottomRight: Radius.circular(4.r),
),
),
margin: EdgeInsets.only(right: 4.w),
child: quickText(item.markingTypeEnum.name,
color: Colors.white, size: 10.sp),
),
Expanded(
child: quickText(item.title,
size: 12.sp,
color: Color.fromRGBO(70, 70, 70, 1),
maxLines: 2),
),
SizedBox(
width: 5.r,
),
Container(
padding: EdgeInsets.symmetric(
vertical: 1.r, horizontal: 5.r),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
border: Border.all(
width: 1.r, color: Color(0xFF4CC793)),
),
child: Center(
child: Text(
item.subjectName,
style: TextStyle(
fontSize: 8.r,
color: Color(0xFF4CC793)),
),
),
)
],
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 6.r),
child: Text('时间:${item.createTime.substring(0,10)}',style: TextStyle(fontSize: 10.sp),),
),
Container(
padding: EdgeInsets.symmetric(vertical: 6.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(6.r),
bottomRight: Radius.circular(6.r)),
color: Colors.white,
boxShadow: [
BoxShadow(
color: const Color.fromRGBO(0, 0, 0, 0.15),
offset: Offset(0, -0.0001), //y轴偏移量
blurRadius: 4, //
spreadRadius: 0, //
)
],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
alignment: Alignment.center,
child: quickText('详情',
color: Color(0xFFFFA115), size: 10.sp),
),
Image.asset(
'assets/images/icon_back_orange.png',
width: 8.r,
height: 8.r,
),
]),
),
],
),
),
);
}),
)
: ListView.builder(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemBuilder: (context, index) {
JobTaskItem item = jobList[index];
return InkWell(
onTap: () {
RouterManager.router.navigateTo(context,
'${RouterManager.answerTrajectoryJobDetailPath}?&jobId=${item.id}&jobName=${Uri.encodeComponent(item.title)}&genderName=${Uri.encodeComponent(item.genderName)}',
transition: getTransition());
},
child: Container(
margin: EdgeInsets.symmetric(vertical: 10.r),
padding: EdgeInsets.only(top: 10.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.r),
color: Colors.white,
boxShadow: [
BoxShadow(
color: const Color.fromRGBO(210, 216, 241, 1),
offset: Offset.zero, //y轴偏移量
blurRadius: 5.8, //
spreadRadius: 0, //
)
],
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//
Padding(
padding: EdgeInsets.symmetric(vertical:14.r,horizontal: 14.r),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 32.w,
height: 18.h,
alignment: Alignment.center,
padding: EdgeInsets.only(left: 2.w),
decoration: BoxDecoration(
color:
const Color.fromRGBO(104, 136, 253, 1),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(14.r),
topRight: Radius.circular(3.r),
bottomLeft: Radius.circular(4.r),
bottomRight: Radius.circular(4.r),
),
),
margin: EdgeInsets.only(right: 4.w),
child: quickText(item.markingTypeEnum.name,
color: Colors.white, size: 10.sp),
),
Expanded(
child: quickText(item.title,
size: 14.sp,
color: Color.fromRGBO(70, 70, 70, 1),
maxLines: 2),
),
SizedBox(
width: 5.r,
),
Container(
padding: EdgeInsets.symmetric(
vertical: 1.r, horizontal: 5.r),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
border: Border.all(
width: 1.r, color: Color(0xFF4CC793)),
),
child: Center(
child: Text(
item.subjectName,
style: TextStyle(
fontSize: 12.r,
color: Color(0xFF4CC793)),
),
),
)
],
),
),
SizedBox(
height: 5.r,
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 14.r),
child: Text('时间:${item.createTime.substring(0,10)}',style: TextStyle(fontSize: 10.sp),),
),
SizedBox(
height: 10.r,
),
Container(height: 1.r,
color: Color(0xFFF5F5F5),),
Container(
padding: EdgeInsets.symmetric(vertical: 10.r),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(6.r),
bottomRight: Radius.circular(6.r)),
color: Colors.white,
/*boxShadow: [
BoxShadow(
color: const Color.fromRGBO(0, 0, 0, 0.15),
offset: Offset(0, -0.0001), //y轴偏移量
blurRadius: 4, //
spreadRadius: 0, //
)
],*/
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
alignment: Alignment.center,
child: quickText('详情',
color: Color(0xFFFFA115), size: 10.sp),
),
Image.asset(
'assets/images/icon_back_orange.png',
width: 8.r,
height: 8.r,
),
]),
),
],
),
),
);
},
itemCount: jobList.length,
)
: MyEmptyWidget();
}
}

View File

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
import 'package:marking_app/common/model/job/job_report_model.dart';
import 'package:marking_app/pages/homework_correction/components/imgDialog.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/easy_refresh/MyEmptyWidget.dart';
import 'package:marking_app/utils/index.dart';
@ -359,7 +360,7 @@ class _ReportTableState extends State<ReportTable> {
onTap: () {
if (item.questionPicture == null)
return ToastUtils.showInfo('当前试题没有原题');
Navigator.push(
/* Navigator.push(
context,
MaterialPageRoute(builder: (_) {
return Scaffold(
@ -369,7 +370,8 @@ class _ReportTableState extends State<ReportTable> {
NetworkImage(item.questionPicture!)),
);
}),
);
);*/
ImageDialog.showImgDialog(context,item.questionPicture!);
},
child: Text('原题',
style: TextStyle(

View File

@ -7,143 +7,155 @@ import 'package:marking_app/utils/index.dart';
class StudentGroupList extends StatelessWidget {
final List studentGroups;
final Function goNextPage;
const StudentGroupList(this.studentGroups,this.goNextPage,{Key? key}) : super(key: key);
final Widget? rightBtn;
const StudentGroupList(this.studentGroups, this.goNextPage,
{Key? key,this.rightBtn})
: super(key: key);
@override
Widget build(BuildContext context) {
return studentGroups != null && studentGroups.length > 0
? isPad()?GridView(
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10.r,
crossAxisSpacing: 10.r,
childAspectRatio: 556 / 112,
),
children: List.generate(studentGroups.length, (index) {
JobStudentGroups item = studentGroups[index];
String classNames = item.classNames.join(" ");
return InkWell(
onTap: (){
goNextPage(item.groupId,item.groupName);
// RouterManager.router.navigateTo(context, '${RouterManager.jobPriorityReviewSetPath}?&groupId=${item.groupId}',transition: getTransition());
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10.r),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10.r)),
color: Colors.white,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(right: 8.r),
child: Text(
item.groupName,
style: TextStyle(
fontSize: 10.sp, color: Color(0xFF6888FD)),
),
? isPad()
? GridView(
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10.r,
crossAxisSpacing: 10.r,
childAspectRatio: 556 / 112,
),
Expanded(
child: Text(
classNames,
style: TextStyle(
fontSize: 10.sp,
color: Color(0xFF999999),
overflow: TextOverflow.ellipsis,
children: List.generate(studentGroups.length, (index) {
JobStudentGroups item = studentGroups[index];
String classNames = item.classNames.join(" ");
return InkWell(
onTap: () {
goNextPage(item.groupId, item.groupName);
// RouterManager.router.navigateTo(context, '${RouterManager.jobPriorityReviewSetPath}?&groupId=${item.groupId}',transition: getTransition());
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10.r),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10.r)),
color: Colors.white,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(right: 8.r),
child: Text(
item.groupName,
style: TextStyle(
fontSize: 10.sp, color: Color(0xFF6888FD)),
),
),
Expanded(
child: Text(
classNames,
style: TextStyle(
fontSize: 10.sp,
color: Color(0xFF999999),
overflow: TextOverflow.ellipsis,
),
textAlign: TextAlign.end,
),
),
rightBtn != null
? rightBtn!
: Container(
margin: EdgeInsets.only(left: 5.r),
height: 20.r,
width: 55.r,
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(20.r)),
color: Color(0xFF6888FD),
),
child: Center(
child: Text(
'详情',
style: TextStyle(
fontSize: 10.sp, color: Colors.white),
),
),
)
],
),
),
textAlign: TextAlign.end,
),
),
Container(
margin: EdgeInsets.only(left: 5.r),
height: 20.r,
width: 55.r,
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(20.r)),
color: Color(0xFF6888FD),
),
child: Center(
child: Text(
'详情',
style: TextStyle(
fontSize: 10.sp, color: Colors.white),
),
),
)
],
),
),
);
}),
):ListView.builder(
shrinkWrap: true,
itemBuilder: (context,index){
JobStudentGroups item = studentGroups[index];
String classNames = item.classNames.join(" ");
return Container(
padding: EdgeInsets.symmetric(vertical:15.r,horizontal: 10.r),
margin: EdgeInsets.only(bottom: 10.r),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10.r)),
color: Colors.white,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(right: 8.r),
child: Text(
item.groupName,
style: TextStyle(
fontSize: 14.sp, color: Color(0xFF6888FD)),
),
),
Expanded(
child: Text(
classNames,
style: TextStyle(
fontSize: 12.sp,
color: Color(0xFF999999),
overflow: TextOverflow.ellipsis,
),
textAlign: TextAlign.end,
),
),
InkWell(
onTap: (){
goNextPage(item.groupId,item.groupName);
// RouterManager.router.navigateTo(context, '${RouterManager.jobPriorityReviewSetPath}?&groupId=${item.groupId}',transition: getTransition());
},
child: Container(
margin: EdgeInsets.only(left: 5.r),
height: 24.r,
width: 55.r,
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(20.r)),
color: Color(0xFF6888FD),
),
child: Center(
child: Text(
'详情',
style: TextStyle(
fontSize: 10.sp, color: Colors.white),
),
),
),
);
}),
)
: ListView.builder(
shrinkWrap: true,
itemBuilder: (context, index) {
JobStudentGroups item = studentGroups[index];
String classNames = item.classNames.join(" ");
return InkWell(
onTap: () {
goNextPage(item.groupId, item.groupName);
// RouterManager.router.navigateTo(context, '${RouterManager.jobPriorityReviewSetPath}?&groupId=${item.groupId}',transition: getTransition());
},
child: Container(
padding:
EdgeInsets.symmetric(vertical: 15.r, horizontal: 10.r),
margin: EdgeInsets.only(bottom: 10.r),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10.r)),
color: Colors.white,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(right: 8.r),
child: Text(
item.groupName,
style: TextStyle(
fontSize: 14.sp, color: Color(0xFF6888FD)),
),
),
Expanded(
child: Text(
classNames,
style: TextStyle(
fontSize: 12.sp,
color: Color(0xFF999999),
overflow: TextOverflow.ellipsis,
),
textAlign: TextAlign.end,
),
),
rightBtn != null
? rightBtn!
: Container(
margin: EdgeInsets.only(left: 5.r),
height: 24.r,
width: 55.r,
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(20.r)),
color: Color(0xFF6888FD),
),
child: Center(
child: Text(
'详情',
style: TextStyle(
fontSize: 10.sp, color: Colors.white),
),
),
)
],
),
),
);
},
itemCount: studentGroups.length,
)
],
),
);
},
itemCount: studentGroups.length,
)
: Padding(
padding: EdgeInsets.only(top: MediaQuery.of(context).size.height/2 - 200.r),
child: MyEmptyWidget(),
);
padding: EdgeInsets.only(
top: MediaQuery.of(context).size.height / 2 - 200.r),
child: MyEmptyWidget(),
);
}
}

View File

@ -8,6 +8,7 @@ class StudentKgTable extends StatefulWidget {
final List bodyList;
final int? fixedRows;
final int? fixedCols;
final Function(String)? questionNumCall;
const StudentKgTable({
Key? key,
@ -15,6 +16,7 @@ class StudentKgTable extends StatefulWidget {
required this.bodyList,
this.fixedCols = 0,
this.fixedRows = 0,
this.questionNumCall,
}) : super(key: key);
@override
@ -29,34 +31,51 @@ class _StudentKgTableState extends State<StudentKgTable> {
String sortString(String str) {
return String.fromCharCodes(str.codeUnits.toList()..sort());
}
DataRow _getRow(int index, [Color? color]) {
assert(index >= 0);
KgDetails item = widget.bodyList[index];
return DataRow2.byIndex(
index: index,
color: color != null ? MaterialStateProperty.all(color): null,
color: color != null ? MaterialStateProperty.all(color) : null,
cells: [
DataCell(Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(item.questionNo,
style: TextStyle(fontSize: 12.sp, color: Color(0xFF6888FD))),
DataCell(
InkWell(
onTap: () {
if (widget.questionNumCall != null) {
widget.questionNumCall!(item.questionNo);
}
},
child: Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(item.questionNo, style: TextStyle(fontSize: 12.sp, color: Color(0xFF6888FD))),
),
),
),
)),
),
DataCell(Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(item.studentAnswer == null?'未作答':item.studentAnswer!,
style: TextStyle(fontSize: 12.sp, color: item.studentAnswer == null?Color(0xFF525252):
item.state == 2?Color(0xFF4CC793):
item.state == 1?Color(0xFFFF7474):item.state == 0?Color(0xFFD3D3D3):Colors.white),
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(
item.studentAnswer == null ? '未作答' : item.studentAnswer!,
style: TextStyle(
fontSize: 12.sp,
color: item.studentAnswer == null
? Color(0xFF525252)
: item.state == 2
? Color(0xFF4CC793)
: item.state == 1
? Color(0xFFFF7474)
: item.state == 0
? Color(0xFFD3D3D3)
: Colors.white),
),
))),
DataCell(Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(item.questionAnswer == null ?'':item.questionAnswer!,
style: TextStyle(fontSize: 12.sp, color: Color(0xFF525252))),
child: Text(item.questionAnswer == null ? '' : item.questionAnswer!, style: TextStyle(fontSize: 12.sp, color: Color(0xFF525252))),
),
)),
],
@ -74,14 +93,10 @@ class _StudentKgTableState extends State<StudentKgTable> {
dataRowHeight: 40.r,
headingRowHeight: 40.r,
border: TableBorder(
horizontalInside: BorderSide(
width: 1, color: Colors.white, style: BorderStyle.solid),
bottom: BorderSide(
width: 1, color: Colors.white, style: BorderStyle.solid),
verticalInside: BorderSide(
width: 1, color: Colors.white, style: BorderStyle.solid)),
headingRowColor: MaterialStateProperty.resolveWith((states) =>
widget.fixedCols! > 0 ? Colors.white : Colors.transparent),
horizontalInside: BorderSide(width: 1, color: Colors.white, style: BorderStyle.solid),
bottom: BorderSide(width: 1, color: Colors.white, style: BorderStyle.solid),
verticalInside: BorderSide(width: 1, color: Colors.white, style: BorderStyle.solid)),
headingRowColor: MaterialStateProperty.resolveWith((states) => widget.fixedCols! > 0 ? Colors.white : Colors.transparent),
headingRowDecoration: BoxDecoration(color: Color(0xFFE6E6E6)),
fixedColumnsColor: Color(0xFFE6E6E6),
fixedCornerColor: Colors.grey[400],
@ -95,14 +110,12 @@ class _StudentKgTableState extends State<StudentKgTable> {
var item = widget.headList[index];
return DataColumn2(
label: Center(
child: Text(item,
style: TextStyle(fontSize: 12.sp, color: Color(0xFF505767))),
child: Text(item, style: TextStyle(fontSize: 12.sp, color: Color(0xFF505767))),
),
// size: ColumnSize.S,
fixedWidth: (MediaQuery.of(context).size.width - 20.r - 28.r)/3,
fixedWidth: (MediaQuery.of(context).size.width - 20.r - 28.r) / 3,
);
}),
rows: List<DataRow>.generate(widget.bodyList.length,
(index) => _getRow(index, Color(0xFFF5F5F5))));
rows: List<DataRow>.generate(widget.bodyList.length, (index) => _getRow(index, Color(0xFFF5F5F5))));
}
}

View File

@ -2,6 +2,8 @@ import 'package:data_table_2/data_table_2.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:marking_app/common/model/job/job_data_report.dart';
import 'package:marking_app/pages/homework_correction/components/imgDialog.dart';
import 'package:marking_app/pages/homework_correction/widget/answer_handwriting.dart';
import 'package:marking_app/utils/common_utils.dart';
import 'package:marking_app/utils/easy_refresh/MyEmptyWidget.dart';
import 'package:photo_view/photo_view.dart';
@ -11,6 +13,7 @@ class StudentZgTable extends StatefulWidget {
final List bodyList;
final int? fixedRows;
final int? fixedCols;
final Function(String)? questionNumCall;
const StudentZgTable({
Key? key,
@ -18,6 +21,7 @@ class StudentZgTable extends StatefulWidget {
required this.bodyList,
this.fixedCols = 0,
this.fixedRows = 0,
this.questionNumCall,
}) : super(key: key);
@override
@ -28,23 +32,23 @@ class _StudentZgTableState extends State<StudentZgTable> {
final ScrollController _controller = ScrollController();
int? _sortColumnIndex;
bool _sortAscending = true;
void showImgDialog(BuildContext context,String imgUrl){
/*void showImgDialog(BuildContext context,String imgUrl){
Navigator.push(
context,
MaterialPageRoute(builder: (_) {
return Scaffold(
appBar: AppBar(),
body: SizedBox(
/* width: MediaQuery.of(context).size.width * 0.6,
height: MediaQuery.of(context).size.height * 0.6,*/
*/ /* width: MediaQuery.of(context).size.width * 0.6,
height: MediaQuery.of(context).size.height * 0.6,*/ /*
child: PhotoView(
imageProvider:
NetworkImage(imgUrl)),
),
);
}),
);
);*/
/* showDialog(context: context, builder: (BuildContext context){
return AlertDialog(
// insetPadding: EdgeInsets.symmetric(vertical: 20.r,horizontal: 20.r),
@ -62,64 +66,75 @@ class _StudentZgTableState extends State<StudentZgTable> {
),
);
});*/
}
// }
DataRow _getRow(int index, [Color? color]) {
assert(index >= 0);
KgDetails item = widget.bodyList[index];
return DataRow2.byIndex(
index: index,
color: color != null ? MaterialStateProperty.all(color): null,
color: color != null ? MaterialStateProperty.all(color) : null,
cells: [
DataCell(Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(item.questionNo,
style: TextStyle(fontSize: 12.sp, color: Color(0xFF6888FD))),
),
)),
DataCell(Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(CommonUtils.second2HMS(item.useTime!),
style: TextStyle(fontSize: 12.sp, color: Color(0xFF525252))),
),
)),
DataCell(InkWell(
onTap: (){
if(item.state != 0){
showImgDialog(context,item.studentAnswer!);
}
onTap: () {
if (widget.questionNumCall != null) {
widget.questionNumCall!(item.questionNo);
}
},
child: Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(item.state!=0 ?'查看':'--',
style: TextStyle(fontSize: 12.sp, color: Color(0xFF3661FE))),
child: Text(item.questionNo, style: TextStyle(fontSize: 12.sp, color: Color(0xFF6888FD))),
),
),
)),
DataCell(Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: item.state == 2?
Image.asset('assets/images/job_personal_correct_icon.png',width: 18.r,height: 18.r,):item.state == 1?
Image.asset('assets/images/job_personal_error_icon.png',width: 10.r,height: 10.r,):Text('', style: TextStyle(fontSize: 12.sp, color: Color(0xFF525252))),
child: Text(CommonUtils.second2HMS(item.useTime!), style: TextStyle(fontSize: 12.sp, color: Color(0xFF525252))),
),
)),
DataCell(InkWell(
onTap: (){
if(item.state==1 || item.state==2){
showImgDialog(context,item.annotateAnswers!);
onTap: () {
if (item.state != 0) {
ImageDialog.showImgDialog(context, item.studentAnswer!);
}
},
child: Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(item.state==1 || item.state==2?'查看':'--',
style: TextStyle(fontSize: 12.sp, color: Color(0xFF3661FE))),
child: Text(item.state != 0 ? '查看' : '--', style: TextStyle(fontSize: 12.sp, color: Color(0xFF3661FE))),
),
),
)),
DataCell(Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: item.state == 2
? Image.asset(
'assets/images/job_personal_correct_icon.png',
width: 18.r,
height: 18.r,
)
: item.state == 1
? Image.asset(
'assets/images/job_personal_error_icon.png',
width: 10.r,
height: 10.r,
)
: Text('', style: TextStyle(fontSize: 12.sp, color: Color(0xFF525252))),
),
)),
DataCell(InkWell(
onTap: () {
if (item.state == 1 || item.state == 2) {
ImageDialog.showImgDialog(context, item.annotateAnswers!);
}
},
child: Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(item.state == 1 || item.state == 2 ? '查看' : '--', style: TextStyle(fontSize: 12.sp, color: Color(0xFF3661FE))),
),
),
)),
@ -138,14 +153,10 @@ class _StudentZgTableState extends State<StudentZgTable> {
headingRowHeight: 40.r,
dataRowHeight: 40.r,
border: TableBorder(
horizontalInside: BorderSide(
width: 1, color: Colors.white, style: BorderStyle.solid),
bottom: BorderSide(
width: 1, color: Colors.white, style: BorderStyle.solid),
verticalInside: BorderSide(
width: 1, color: Colors.white, style: BorderStyle.solid)),
headingRowColor: MaterialStateProperty.resolveWith((states) =>
widget.fixedCols! > 0 ? Colors.white : Colors.transparent),
horizontalInside: BorderSide(width: 1, color: Colors.white, style: BorderStyle.solid),
bottom: BorderSide(width: 1, color: Colors.white, style: BorderStyle.solid),
verticalInside: BorderSide(width: 1, color: Colors.white, style: BorderStyle.solid)),
headingRowColor: MaterialStateProperty.resolveWith((states) => widget.fixedCols! > 0 ? Colors.white : Colors.transparent),
headingRowDecoration: BoxDecoration(color: Color(0xFFE6E6E6)),
fixedColumnsColor: Color(0xFFE6E6E6),
fixedCornerColor: Colors.grey[400],
@ -159,14 +170,12 @@ class _StudentZgTableState extends State<StudentZgTable> {
var item = widget.headList[index];
return DataColumn2(
label: Center(
child: Text(item,
style: TextStyle(fontSize: 12.sp, color: Color(0xFF505767))),
child: Text(item, style: TextStyle(fontSize: 12.sp, color: Color(0xFF505767))),
),
// size: ColumnSize.S,
fixedWidth: (MediaQuery.of(context).size.width - 20.r - 28.r)/5,
fixedWidth: (MediaQuery.of(context).size.width - 20.r - 28.r) / 5,
);
}),
rows: List<DataRow>.generate(widget.bodyList.length,
(index) => _getRow(index, Color(0xFFF5F5F5))));
rows: List<DataRow>.generate(widget.bodyList.length, (index) => _getRow(index, Color(0xFFF5F5F5))));
}
}

View File

@ -9,13 +9,17 @@
import 'dart:convert';
import 'dart:io';
import 'package:collection/collection.dart';
import 'package:dio/dio.dart';
import 'package:dio/adapter.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:functional_widget_annotation/functional_widget_annotation.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:marking_app/common/config/request_config.dart';
import 'package:marking_app/common/mixin/common.dart';
@ -29,6 +33,9 @@ import 'package:marking_app/common/model/user/user_login.dart';
import 'package:marking_app/common/model/user/user_login_params.dart';
import 'package:marking_app/provider/user_provider.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/sys_protocol.dart';
part 'index.g.dart';
class TheLogin extends StatefulHookConsumerWidget {
const TheLogin({Key? key}) : super(key: key);
@ -53,15 +60,19 @@ class _TheLoginState extends ConsumerState<TheLogin> with CommonMixin {
//
late final TextEditingController _userNameController;
late final TextEditingController _passwordController;
int? lastTimeSchoolId; // ID
int? schoolId;
List<UseLoginSchool> schools = []; //
late final FocusNode _pwdFocus; //
late final FocusNode _theFocus;
bool keepPwd = false; //
bool readAgreement = true; //
bool readAgreement = false; //
bool canLogin = true;
bool hasNameVal = false;
bool _isShowPwd = true;
bool showRegister = false;
void _showPassword() {
setState(() {
@ -71,19 +82,14 @@ class _TheLoginState extends ConsumerState<TheLogin> with CommonMixin {
@override
void initState() {
Future.delayed(Duration(seconds: 1), () => sysProtocol(context));
Future(() {
// Provider
ref.read(userTokenProvider.notifier).clean(); //
});
getShowRegister();
super.initState();
dio = Dio(
BaseOptions(
contentType: "application/json",
connectTimeout: 8000,
receiveTimeout: 8000,
),
);
dio = Dio(BaseOptions(contentType: "application/json", connectTimeout: 8000, receiveTimeout: 8000));
dio.interceptors.add(LogInterceptor(responseBody: true, requestBody: true)); //
setHttpsPEM();
@ -99,17 +105,60 @@ class _TheLoginState extends ConsumerState<TheLogin> with CommonMixin {
setState(() {
_passwordController.text = valMap['pwd'];
_userNameController.text = valMap['account'];
lastTimeSchoolId = int.tryParse(valMap['schoolId']);
print('原始学校ID $schoolId');
keepPwd = true;
});
});
}
void getShowRegister() async {
try {
var client = await getClient();
BaseStructureResult<dynamic> resultData = await client.showRegister();
if (resultData.success) setState(() => showRegister = resultData.data);
} catch (e) {}
}
//
void getSchoolData(String loginName) async {
if (loginName.length != 0) {
try {
if (loginName == '18888888888') {
schoolId = 10079;
return;
}
var _client = await getClient();
var res = await _client.toLoginGetSchools(loginName);
if (res.success) {
schools = res.data ?? [];
UseLoginSchool? schoolElement;
if (lastTimeSchoolId != null) schoolElement = schools.firstWhereOrNull((e) => e.schoolId == lastTimeSchoolId);
if (schoolElement != null)
schoolId = schoolElement.schoolId;
else
schoolId = schools[0].schoolId;
setState(() {});
return;
}
} catch (e) {}
}
if (schools.isNotEmpty || schoolId != null) {
schools = [];
schoolId = null;
setState(() {});
}
}
void userNameListener() {
String userName = _userNameController.text;
String userName = _userNameController.text.trim();
int useNameLength = userName.length;
bool hasNameValNew = useNameLength > 0;
if (!hasNameValNew) lastTimeSchoolId = null;
if (hasNameValNew != hasNameVal) toUpState(setState, () => hasNameVal = hasNameValNew, mounted);
const isProd = bool.fromEnvironment('dart.vm.product');
getSchoolData(userName); //
if (!isProd && useNameLength == 11) {
_passwordController.text = userName.substring(useNameLength - 6);
}
@ -225,7 +274,8 @@ class _TheLoginState extends ConsumerState<TheLogin> with CommonMixin {
controller: _passwordController,
keyboardType: TextInputType.number,
maxLines: 1,
obscureText: _isShowPwd, //
obscureText: _isShowPwd,
//
textInputAction: TextInputAction.go,
onSubmitted: (val) => toLogin(),
style: TextStyle(
@ -247,9 +297,11 @@ class _TheLoginState extends ConsumerState<TheLogin> with CommonMixin {
labelStyle: TextStyle(fontSize: 16.sp, color: const Color.fromRGBO(148, 163, 182, 1)),
),
),
SizedBox(
height: 12.h,
),
$SchoolDataDropDown(schools, schoolId, (int? id) {
schoolId = id;
lastTimeSchoolId = null;
}),
SizedBox(height: 12.h),
Row(
children: [
Container(
@ -274,18 +326,19 @@ class _TheLoginState extends ConsumerState<TheLogin> with CommonMixin {
FocusScope.of(context).requestFocus(_theFocus);
setState(() => keepPwd = !keepPwd);
},
child: Text(
'记住密码',
style: TextStyle(
fontSize: 14.sp,
color: const Color.fromRGBO(148, 163, 182, 1),
),
),
child: Text('记住密码', style: TextStyle(fontSize: 14.sp, color: const Color.fromRGBO(148, 163, 182, 1))),
),
Spacer(),
if (showRegister == true)
InkWell(
onTap: () {
RouterManager.router.navigateTo(context, RouterManager.registerPath);
},
child: Text('注册', style: TextStyle(fontSize: 14.sp, color: const Color.fromRGBO(148, 163, 182, 1)))),
],
),
InkWell(
onTap: toLogin,
onTap: () => easyThrottle('TO_GO_LOGOIN', toLogin),
child: Container(
margin: EdgeInsets.symmetric(vertical: 10.h),
decoration: BoxDecoration(
@ -298,9 +351,7 @@ class _TheLoginState extends ConsumerState<TheLogin> with CommonMixin {
spreadRadius: 0.5, //
)
],
borderRadius: BorderRadius.all(
Radius.circular(8.w),
),
borderRadius: BorderRadius.all(Radius.circular(8.w)),
),
alignment: Alignment.center,
width: double.infinity,
@ -337,7 +388,7 @@ class _TheLoginState extends ConsumerState<TheLogin> with CommonMixin {
transition: getTransition(),
);
},
child: quickText('请仔细阅读', size: 13.sp),
child: quickText('我已阅读', size: 11.sp),
),
InkWell(
onTap: () {
@ -347,9 +398,25 @@ class _TheLoginState extends ConsumerState<TheLogin> with CommonMixin {
transition: getTransition(),
);
},
child: const Text(
child: quickText(
'《用户协议》',
style: TextStyle(color: Colors.deepOrangeAccent),
size: 12.sp,
color: Colors.deepOrangeAccent,
),
),
quickText('', size: 10.sp),
InkWell(
onTap: () {
RouterManager.router.navigateTo(
context,
'${RouterManager.agreementPath}?type=${AGREEMENT_KEY.PRIVACY_GREEMENT.name}',
transition: getTransition(),
);
},
child: quickText(
'《隐私协议》',
size: 12.sp,
color: Colors.deepOrangeAccent,
),
),
],
@ -368,27 +435,63 @@ class _TheLoginState extends ConsumerState<TheLogin> with CommonMixin {
void toLogin() async {
if (!canLogin) return;
setState(() => canLogin = false);
void toMsg(msg) {
ToastUtils.showError(msg);
Future.delayed(Duration.zero, () => ToastUtils.showError(msg));
setState(() => canLogin = true);
}
FocusScope.of(context).requestFocus(_theFocus);
String userName = _userNameController.text.trim();
String userPwd = _passwordController.text.trim();
if (userName == '') return toMsg('请填写用户账号');
if (userPwd == '') return toMsg('请填写密码再试');
if (!readAgreement) return toMsg('请阅读用户协议');
String userPwdMd5 = CommonUtils.generateMD5(userPwd);
EasyLoading.show(status: 'loading...');
try {
BaseStructureResult<dynamic> resultData = await client.toLogin(UserLoginParams(userName, userPwdMd5));
UserLogin? userData =
resultData.code == 200 && resultData.data != null ? UserLogin.fromJson(resultData.data) : null;
setState(() => canLogin = false);
FocusScope.of(context).requestFocus(_theFocus);
if (!readAgreement) {
var resFlag = await showDialog<bool>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return CupertinoAlertDialog(
title: quickText('用户协议及隐私协议', size: 14.sp, color: Color.fromARGB(255, 53, 52, 52)),
content: SingleChildScrollView(
padding: EdgeInsets.only(top: 4.h),
child: RichText(
text: TextSpan(
text: '为了更好地保障您的合法权益,请您阅读并同意以下协议',
style: TextStyle(color: Color.fromARGB(255, 137, 138, 139), fontSize: 11.sp),
children: <TextSpan>[
TextSpan(text: '《用户协议》《隐式协议》', style: TextStyle(color: Colors.deepOrangeAccent, fontSize: 13.sp)),
],
),
),
),
actions: <Widget>[
CupertinoDialogAction(
child: Text("取消", style: TextStyle(color: Color.fromARGB(255, 58, 58, 58))),
onPressed: () => Navigator.of(context).pop(false),
),
CupertinoDialogAction(
child: Text("确定"),
onPressed: () => Navigator.of(context).pop(true),
),
],
);
},
);
if (!resFlag!) return;
setState(() => readAgreement = true);
}
String userName = _userNameController.text.trim();
String userPwd = _passwordController.text.trim();
if (userName == '') return toMsg('请填写用户账号');
if (userPwd == '') return toMsg('请填写密码再试');
if (!readAgreement) return toMsg('请勾选我已阅读用户协议和隐私协议');
if (schoolId == null) return toMsg('请选择所在学校');
String userPwdMd5 = CommonUtils.generateMD5(userPwd);
print('userPwdMd5=$userPwdMd5');
EasyLoading.show(status: 'loading...');
BaseStructureResult<dynamic> resultData = await client.toLogin(UserLoginParams(userName, userPwdMd5, schoolId!));
UserLogin? userData = resultData.code == 200 && resultData.data != null ? UserLogin.fromJson(resultData.data) : null;
if (resultData.code != 200 || userData?.accessToken == null || userData?.accessToken == '') {
return toMsg(resultData.message ?? '登录失败,请重试');
}
@ -397,6 +500,7 @@ class _TheLoginState extends ConsumerState<TheLogin> with CommonMixin {
fastData.setToken(userData!.accessToken);
BaseStructureResult<UserInfo> userRes = await client.getUserInfo('Bearer ${userData.accessToken}');
if (userRes.code != 200 || userRes.data == null) {
throw Exception('登录失败,请重试');
}
@ -404,7 +508,7 @@ class _TheLoginState extends ConsumerState<TheLogin> with CommonMixin {
fastData.setUser(userRes.data!).then((value) {
//
if (keepPwd) {
fastData.setUserPwdAndAccount({'pwd': userPwd, 'account': userName});
fastData.setUserPwdAndAccount({'pwd': userPwd, 'account': userName, 'schoolId': schoolId.toString()});
}
//
ref.read(userProvider.notifier).initUserInfo();
@ -443,6 +547,45 @@ class _TheLoginState extends ConsumerState<TheLogin> with CommonMixin {
return toMsg(msg ?? '登录失败,请重试');
} finally {
EasyLoading.dismiss();
setState(() => canLogin = true);
}
}
}
@hwidget
Widget $schoolDataDropDown(BuildContext context, List<UseLoginSchool> schools, int? schoolId, void Function(int? id) call) {
var useSchool = useState(schools);
var useSchoolId = useState(schoolId);
useValueChanged<List<UseLoginSchool>, void>(schools, (_, __) => useSchool.value = schools);
useValueChanged<int?, void>(schoolId, (_, __) => useSchoolId.value = schoolId);
if (useSchool.value.isEmpty) return SizedBox();
return Padding(
padding: EdgeInsets.only(top: 24.h),
child: Column(
children: [
Container(alignment: Alignment.topLeft, child: quickText('登录学校', size: 12.sp, color: const Color.fromRGBO(148, 163, 182, 1))),
Container(
height: 40.h,
width: double.infinity,
child: DropdownButton<int>(
value: useSchoolId.value,
iconSize: 18.r,
elevation: 16,
isExpanded: true,
padding: EdgeInsets.only(right: 4.w),
icon: const Icon(Icons.keyboard_arrow_down_rounded),
style: TextStyle(color: Colors.deepPurple),
underline: Container(height: 0.6.h, color: const Color.fromRGBO(80, 87, 103, 1)),
onChanged: (int? id) {
call(id);
useSchoolId.value = schoolId;
},
items: useSchool.value.map((e) => DropdownMenuItem<int>(value: e.schoolId, child: quickText(e.schoolName, size: 12.sp))).toList(),
),
)
],
),
);
}

View File

@ -16,7 +16,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:marking_app/common/mixin/common.dart';
import 'package:marking_app/common/model/common/base_structure_result.dart';
import 'package:marking_app/common/model/user/user_info.dart';
import 'package:marking_app/pages/homework_correction/index.dart';
import 'package:marking_app/pages/reports/index.dart';
import 'package:marking_app/provider/do_marking_provider.dart';
import 'package:marking_app/provider/upload_file_provider.dart';
@ -30,6 +29,9 @@ import 'package:marking_app/provider/user_provider.dart';
import 'package:marking_app/utils/index.dart';
import 'package:marking_app/utils/request/rest_client.dart';
import 'package:package_info/package_info.dart';
import 'package:url_launcher/url_launcher.dart';
import 'homework_correction/job_home.dart';
class TheMainPage extends StatefulHookConsumerWidget {
const TheMainPage({Key? key}) : super(key: key);
@ -49,7 +51,8 @@ class TheMainPageState extends ConsumerState<TheMainPage> with CommonMixin {
final List<Widget> _bodyList = [
const TheHomePage(),
const TheMarking(),
const HomeworkCorrection(),
// const HomeworkCorrection(),
const JobHome(),
const TheReport()
];
int tabIndex = 0;
@ -71,10 +74,11 @@ class TheMainPageState extends ConsumerState<TheMainPage> with CommonMixin {
// APP升级校验在登录后
_userListener = ref.read(userProvider.notifier).addListener((state) {
if (state.id != '0' && state.id != '') {
if (!showUpgrade) {
getAppUpgrade(state);
}
if (!showUpgrade) getAppUpgrade(state);
_timer?.cancel();
_timer = Timer.periodic(Duration(seconds: 40), (e) {
String? routeName = ModalRoute.of(context)?.settings.name;
if (routeName == RouterManager.loginPath) return; // APP
if (!showUpgrade) getAppUpgrade(state);
});
}
@ -85,6 +89,7 @@ class TheMainPageState extends ConsumerState<TheMainPage> with CommonMixin {
if (!value) {
return toLoginPage(context);
}
if (ref.read(userProvider).id == '540117143121989') return;
ref.read(userReportProvider.notifier).initUserReport(); //
}); // token
//
@ -102,9 +107,10 @@ class TheMainPageState extends ConsumerState<TheMainPage> with CommonMixin {
}
void getAppUpgrade(UserInfo user) async {
if (!bool.fromEnvironment('dart.vm.product')) return;
try {
showUpgrade = true;
if (user.loginName == '18888888888') return;
if (['18888888888'].contains(user.loginName)) return;
//
String deviceInfo;
int deviceType;
@ -130,14 +136,8 @@ class TheMainPageState extends ConsumerState<TheMainPage> with CommonMixin {
// String buildNumber = packageInfo.buildNumber; //
SystemVersion data = result.data!;
Map json = {
'downloadPath': data.apkUrl,
'version': data.version,
'systemType': deviceType,
'description': data.description
};
UpdateAppEvent updateAppEvent =
UpdateAppEvent.fromJson(json, localVersion, deviceInfo, appName, packageName, typeName: 'systemType');
Map json = {'downloadPath': data.apkUrl, 'version': data.version, 'systemType': deviceType, 'description': data.description};
UpdateAppEvent updateAppEvent = UpdateAppEvent.fromJson(json, localVersion, deviceInfo, appName, packageName, typeName: 'systemType');
if (updateAppEvent.upgrade) {
await UpdateDialog.showUpdateDialog(context, updateAppEvent);
}
@ -160,7 +160,8 @@ class TheMainPageState extends ConsumerState<TheMainPage> with CommonMixin {
child: Scaffold(
body: PageView(
controller: _pageController,
physics: const BouncingScrollPhysics(),
// physics: const BouncingScrollPhysics(),
physics: NeverScrollableScrollPhysics(),
onPageChanged: (index) => toUpState(setState, () => tabIndex = index, mounted),
children: _bodyList,
),

View File

@ -0,0 +1,124 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:marking_app/common/model/enum/review_marks_bottom_btns_enum.dart';
import 'package:marking_app/common/model/event_bus/bottom_annotation_switch_cleanall.dart';
import 'package:marking_app/pages/common/event_bus_mixin.dart';
import 'package:marking_app/utils/anti_shake_throttling.dart';
import 'package:marking_app/utils/my_text.dart';
import '../provider/do_paper_bottom_review_marks_provider.dart';
//
class DoPaperBottomReviewMarks extends StatefulHookConsumerWidget {
const DoPaperBottomReviewMarks({super.key});
@override
ConsumerState<DoPaperBottomReviewMarks> createState() => _DoPaperBottomReviewMarksState();
}
class _DoPaperBottomReviewMarksState extends ConsumerState<DoPaperBottomReviewMarks> with EventBusMixin<BottomAnnotationSwitchCleanallOfMarking> {
@override
void initState() {
super.initState();
}
@override
void dispose() {
// TODO: implement dispose
eventCancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
var btnEnum = ref.watch(doPaperBottomReviewMarksProvider);
Color actionColor = Theme.of(context).primaryColor.withOpacity(0.9);
return Positioned(
left: 3.w,
bottom: 6.h,
child: AbsorbPointer(
absorbing: false,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50.r),
color: const Color.fromRGBO(24, 32, 32, 0.1),
),
padding: EdgeInsets.symmetric(horizontal: 10.w),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
//
IconButton(
onPressed: () => easyThrottle(
'REVIEW_MARKS_BOTTOM_BTNS',
() => ref.read(doPaperBottomReviewMarksProvider.notifier).setState(ReviewMarksBottomBtnsEnum.DRAG),
),
padding: EdgeInsets.zero,
icon: Icon(Icons.back_hand_outlined, color: btnEnum == ReviewMarksBottomBtnsEnum.DRAG ? actionColor : Colors.white, size: 34.r),
),
SizedBox(width: 4.w),
//
IconButton(
onPressed: () => easyThrottle(
'REVIEW_MARKS_BOTTOM_BTNS',
() => ref.read(doPaperBottomReviewMarksProvider.notifier).setState(ReviewMarksBottomBtnsEnum.HANDWRITING),
),
padding: EdgeInsets.zero,
icon: Icon(Icons.create_outlined, color: btnEnum == ReviewMarksBottomBtnsEnum.HANDWRITING ? actionColor : Colors.white, size: 34.r),
),
SizedBox(width: 4.w),
// ==>
IconButton(
onPressed: () => easyThrottle(
'REVIEW_MARKS_BOTTOM_BTNS',
duration: const Duration(milliseconds: 100),
() => eventFire(model: BottomAnnotationSwitchCleanallOfMarking(previousStep: true)),
),
padding: EdgeInsets.zero,
icon: Icon(Icons.reply_outlined,
color: btnEnum == ReviewMarksBottomBtnsEnum.RETURN_PREVIOUS_LEVEL ? actionColor : Colors.white, size: 34.r),
),
SizedBox(width: 4.w),
// ==>
IconButton(
onPressed: () => easyThrottle(
'REVIEW_MARKS_BOTTOM_BTNS',
duration: const Duration(milliseconds: 100),
() async {
var resFlag = await showDialog<bool>(
context: context,
builder: (BuildContext context) {
return CupertinoAlertDialog(
title: quickText('撤销批阅痕迹', size: 14.sp, color: Color.fromARGB(255, 53, 52, 52)),
content: SingleChildScrollView(
padding: EdgeInsets.only(top: 4.h),
child: RichText(text: TextSpan(text: '请确认需要撤销所有批阅痕迹?', style: TextStyle(color: Color.fromARGB(255, 58, 58, 58)))),
),
actions: <Widget>[
CupertinoDialogAction(
child: Text("取消", style: TextStyle(color: Color.fromARGB(255, 58, 58, 58))),
onPressed: () => Navigator.of(context).pop(false),
),
CupertinoDialogAction(
child: Text("确定"),
onPressed: () => Navigator.of(context).pop(true),
),
],
);
},
);
if (resFlag == true) eventFire(model: BottomAnnotationSwitchCleanallOfMarking(cleanAll: true));
},
),
padding: EdgeInsets.zero,
icon: Icon(Icons.reply_all_outlined, color: btnEnum == ReviewMarksBottomBtnsEnum.CLEAR_ALL ? actionColor : Colors.white, size: 34.r),
),
],
),
),
),
);
}
}

View File

@ -14,6 +14,7 @@ import 'package:achievement_view/achievement_view.dart';
import 'package:collection/collection.dart';
import 'package:dotted_border/dotted_border.dart';
import 'package:dropdown_search/dropdown_search.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
@ -28,6 +29,8 @@ import 'package:marking_app/common/model/common/base_structure_result.dart';
import 'package:marking_app/common/model/common/upload_img_secret_key.dart';
import 'package:marking_app/common/model/enum/KeyboardType.dart';
import 'package:marking_app/common/model/enum/marking_list_type.dart';
import 'package:marking_app/common/model/enum/review_marks_bottom_btns_enum.dart';
import 'package:marking_app/common/model/event_bus/bottom_annotation_switch_cleanall.dart';
import 'package:marking_app/common/model/marking/current_review_task.dart';
import 'package:marking_app/common/model/marking/do_marking_keyboard_model.dart';
import 'package:marking_app/common/model/marking/keyboard_assist_event.dart';
@ -52,6 +55,8 @@ import 'package:marking_app/components/marking/review_records_view.dart';
import 'package:marking_app/components/marking/selectable_keyboard_bottom.dart';
import 'package:marking_app/pages/common/event_bus_mixin.dart';
import 'package:marking_app/pages/marking/hooks/use_zoomImage_history_utils.dart';
import 'package:marking_app/pages/marking/provider/do_paper_bottom_review_marks_provider.dart';
import 'package:marking_app/pages/marking/provider/draw_marking_provider.dart';
import 'package:marking_app/pages/marking/provider/rating_progress_provider.dart';
import 'package:marking_app/provider/annotation_graffiti_switch_provider.dart';
import 'package:marking_app/provider/do_marking_provider.dart';
@ -66,6 +71,7 @@ import 'package:marking_app/utils/request/rest_client.dart';
import 'package:percent_indicator/percent_indicator.dart';
import 'package:wakelock/wakelock.dart';
import 'components/do_paper_bottom_review_marks.dart';
import 'hooks/use_abnormal.dart';
part 'do_papers.g.dart';
@ -138,6 +144,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
bool _completionPromptTab = false; // tab下试题完成并提示
bool _reviewCompletedPrompted = false; //
bool annotationTips = false; //
// bool _switchQueTypePrompt = false; //
@ -157,6 +164,10 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
fToast.init(context);
Future.delayed(const Duration(seconds: 0)).then((onValue) {
ref.read(annotationGraffitiSwitchProvider.notifier).init();
//
ref.read(drawMarkingProvider.notifier).setState(DrawMarkingVal([], []));
//
ref.read(doPaperBottomReviewMarksProvider.notifier).setState(ReviewMarksBottomBtnsEnum.DRAG);
});
//
@ -174,9 +185,8 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
screenDirectionSwitch(state.screenDirection);
} else {
ScreenDirection nowScreenDirection = state.screenDirection; //
ScreenDirection theOrientation = MediaQuery.of(context).orientation == Orientation.landscape
? ScreenDirection.HORIZONTAL_SCREEN
: ScreenDirection.VERTICAL_SCREEN;
ScreenDirection theOrientation =
MediaQuery.of(context).orientation == Orientation.landscape ? ScreenDirection.HORIZONTAL_SCREEN : ScreenDirection.VERTICAL_SCREEN;
if (theOrientation != nowScreenDirection) {
screenDirectionSwitch(nowScreenDirection);
}
@ -188,6 +198,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
setTimeOut(300, () {
eventFireSub(model: SwitchKeyboardToReloadImages(true));
});
eventOn(callback: (BottomAnnotationSwitchCleanallOfMarking item) async {});
});
params = MarkingTextQuestionParams(
@ -243,8 +254,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
bool isHorizontal = direction == ScreenDirection.HORIZONTAL_SCREEN;
Future.delayed(Duration.zero, () {
SystemChrome.setPreferredOrientations(
[isHorizontal ? DeviceOrientation.landscapeLeft : DeviceOrientation.portraitUp]);
SystemChrome.setPreferredOrientations([isHorizontal ? DeviceOrientation.landscapeLeft : DeviceOrientation.portraitUp]);
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []);
setTimeOut(1000, () => toUpState(setState, () => annotationsFlag = true, mounted));
});
@ -260,8 +270,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
return null;
}
currentQuestion!.papersUrlStr = paperUrls;
currentQuestion!.papersUrl =
paperUrls.asMap().keys.map((e) => GalleryExampleItemModel(id: e.toString(), resource: paperUrls[e])).toList();
currentQuestion!.papersUrl = paperUrls.asMap().keys.map((e) => GalleryExampleItemModel(id: e.toString(), resource: paperUrls[e])).toList();
return currentQuestion!.papersUrl;
}
@ -426,8 +435,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
Future<void> submitTestQuestions(BuildContext theContext, MarkingTextQuestion data) async {
Timer timer = Timer(const Duration(milliseconds: 300), () => ToastUtils.showLoading());
try {
if (widget.markingtype == MarkingListType.NORMAL && currentQuestion!.isException)
return ToastUtils.showError('异常题,不允许再评分');
if (widget.markingtype == MarkingListType.NORMAL && currentQuestion!.isException) return ToastUtils.showError('异常题,不允许再评分');
if (currentQuestion == null) {
return ToastUtils.showError('提交失败,请退出重试。');
@ -463,15 +471,15 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
RestClient client = await getClient();
String? commentImageUrlStr;
List<String>? commentImageUrl = currentQuestion?.commentImageUrlTodo;
if (commentImageUrl?.isEmpty ?? true) commentImageUrl = currentQuestion?.commentImageUrl;
List<String>? commentImageUrl = (currentQuestion?.commentImageUrl.isNotEmpty ?? false) || res?.url != null
? currentQuestion?.commentImageUrlMap.values.map((original) {
String withoutProtocol = original.replaceAll(RegExp(r"https?:"), "");
if (withoutProtocol.contains('?')) withoutProtocol = withoutProtocol.split('?').first;
return withoutProtocol;
}).toList()
: null;
if (commentImageUrl?.isNotEmpty ?? false) commentImageUrlStr = jsonEncode(commentImageUrl);
// bool excessContinue =
// _currentTab?.agreementExcess == null ? true : _currentTab!.agreementExcess!; // true
bool isExit = false;
MarkingTextQuestionTab? nextTag;
BaseStructureResult<bool> result = await client.submitTestQuestionsOfExam(SubmitExamParams(
widget.markingUserId,
detailId,
@ -507,6 +515,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
e.isFinish = true;
}
}
annotationTips = false;
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(
@ -758,12 +767,44 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
return ToastUtils.getFluttertoast(context: context, msg: '请先评分后提交再进入下一题');
}
print(annotationTips);
if (annotationTips && currentQuestion != null) {
//
var resFlag = await showDialog<bool>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return CupertinoAlertDialog(
title: quickText('未提交批注提示', size: 14.sp, color: Color.fromARGB(255, 53, 52, 52)),
content: SingleChildScrollView(
padding: EdgeInsets.only(top: 4.h),
child: RichText(text: TextSpan(text: '当前批注未提交切换试题将清空本次笔迹,是否继续?', style: TextStyle(color: Color.fromARGB(255, 58, 58, 58)))),
),
actions: <Widget>[
CupertinoDialogAction(
child: Text("提交", style: TextStyle(color: Color.fromARGB(255, 58, 58, 58))),
onPressed: () => Navigator.of(context).pop(false),
),
CupertinoDialogAction(
child: Text("继续"),
onPressed: () => Navigator.of(context).pop(true),
),
],
);
},
);
if (!resFlag!) {
//
return submitTestQuestions(context, currentQuestion!);
}
}
int detailId = theId ?? (isNext ? currentQuestion!.nextId : currentQuestion!.prevId);
bool isReview = widget.isReview;
if (theId != null && _currentTab != null && theQuestionNum != _currentTab!.questionNum) {
MarkingTextQuestionTab? _foundCrrentTab =
_currentTabs.firstWhereOrNull((element) => element.questionNum == theQuestionNum);
MarkingTextQuestionTab? _foundCrrentTab = _currentTabs.firstWhereOrNull((element) => element.questionNum == theQuestionNum);
if (_foundCrrentTab != null) {
_currentTab = _foundCrrentTab;
}
@ -791,11 +832,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
// score: continueScoring hasSubtopic; cleanScore:
Future<void> synchroScore(
{required double score,
required bool continueScoring,
required bool hasSubtopic,
bool allWrong = false,
bool cleanScore = false}) async {
{required double score, required bool continueScoring, required bool hasSubtopic, bool allWrong = false, bool cleanScore = false}) async {
if (currentQuestion == null) return;
if (cleanScore) {
@ -879,8 +916,8 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
res.data = res.data!.where((element) => !(element.isFinished && element.finishCount == 0)).toList();
// 便tags key是题号
Map<String, MarkingTextQuestionTab> _currentTabsMap = Map<String, MarkingTextQuestionTab>.fromIterable(_currentTabs,
key: (item) => item.questionNum, value: (item) => item);
Map<String, MarkingTextQuestionTab> _currentTabsMap =
Map<String, MarkingTextQuestionTab>.fromIterable(_currentTabs, key: (item) => item.questionNum, value: (item) => item);
MarkingTextQuestionTab? theCurrentTab;
String currentTagQueNum = _currentTab!.questionNum;
res.data!.forEach((e) {
@ -918,31 +955,25 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
if (!widget.exceptional && _currentTabs.length <= 0 && _currentTab == null) {
// tag为空tag数据并且为对应的tag赋值上分值步长
RestClient client = await getClient();
List<BaseStructureResult> res = await Future.wait([
client.getTestQuestionsOfTab(widget.markingUserId),
client.getTestQuestionsOfTabStepSize(widget.examSubjectId)
]);
BaseStructureResult<List<MarkingTextQuestionTab>> resultTab =
res[0] as BaseStructureResult<List<MarkingTextQuestionTab>>;
BaseStructureResult<List<MarkingTextQuestionTabStepSize>> resultTabStep =
res[1] as BaseStructureResult<List<MarkingTextQuestionTabStepSize>>;
List<BaseStructureResult> res =
await Future.wait([client.getTestQuestionsOfTab(widget.markingUserId), client.getTestQuestionsOfTabStepSize(widget.examSubjectId)]);
BaseStructureResult<List<MarkingTextQuestionTab>> resultTab = res[0] as BaseStructureResult<List<MarkingTextQuestionTab>>;
BaseStructureResult<List<MarkingTextQuestionTabStepSize>> resultTabStep = res[1] as BaseStructureResult<List<MarkingTextQuestionTabStepSize>>;
if ((!resultTab.success || (resultTab.data?.isEmpty ?? true)) ||
(!resultTabStep.success || (resultTabStep.data?.isEmpty ?? true)) ||
(resultTabStep.data!.length < resultTab.data!.length)) {
throw Error();
}
Map<String, double> tabStepMap = Map<String, double>.fromIterable(resultTabStep.data!,
key: (item) => item.questionNum, value: (item) => item.scoreInterval);
Map<String, double> tabStepMap =
Map<String, double>.fromIterable(resultTabStep.data!, key: (item) => item.questionNum, value: (item) => item.scoreInterval);
resultTab.data = resultTab.data!.where((element) => !(element.isFinished && element.finishCount == 0)).toList();
resultTab.data!.forEach((element) => element.setStepSize(tabStepMap[element.questionNum] ?? 1.0));
_currentTabs = resultTab.data!;
// tabs批次下第一个没有完成数据
currentTab = resultTab.data!.firstWhere(
tabQuestionNum == null ? firstWhereCall : (e) => e.questionNum == tabQuestionNum,
orElse: () =>
MarkingTextQuestionTab(isFinished: false, questionNum: '0.0', total: 0, finishCount: 0, isExcess: false));
currentTab = resultTab.data!.firstWhere(tabQuestionNum == null ? firstWhereCall : (e) => e.questionNum == tabQuestionNum,
orElse: () => MarkingTextQuestionTab(isFinished: false, questionNum: '0.0', total: 0, finishCount: 0, isExcess: false));
if (currentTab.questionNum == '0.0') {
// tab设置为第一个
@ -1025,8 +1056,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
if (hasNext) {
// tab
return _currentTabs.firstWhere(firstWhereCall,
orElse: () => MarkingTextQuestionTab(
questionNum: '0.0', total: 0, finishCount: 0, isExcess: false, isFinished: false));
orElse: () => MarkingTextQuestionTab(questionNum: '0.0', total: 0, finishCount: 0, isExcess: false, isFinished: false));
}
if (tabQuestionNum != null) {
@ -1036,8 +1066,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
if (resetting) {
//
MarkingTextQuestionTab theMarking = _currentTabs.firstWhere(firstWhereCall,
orElse: () => MarkingTextQuestionTab(
questionNum: '0.0', total: 0, finishCount: 0, isExcess: false, isFinished: false));
orElse: () => MarkingTextQuestionTab(questionNum: '0.0', total: 0, finishCount: 0, isExcess: false, isFinished: false));
if (theMarking.questionNum != '0.0') {
currentTab = theMarking;
}
@ -1108,6 +1137,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
// bool flagInputKeyboardGuidePage = await FastData.getInstance().getInputKeyboardGuidePage(); //
try {
theRequesting = true;
RestClient client = await getClient();
MarkingTextQuestionTab? temTab;
bool isNormal = !widget.exceptional;
@ -1116,8 +1146,6 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
MarkingTextQuestionTab? oldCurrentTab = _currentTab;
temTab = await getTabsData(tabQuestionNum: tabQuestionNum, resetting: resetting); // tag tag
print('当前选中类型:${temTab.questionNum}');
MarkingTextQuestionTabParams theParam = tabParams.setQuestionNum(
tab: temTab,
locaQuestionNum: oldCurrentTab?.questionNum,
@ -1140,11 +1168,16 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
setTimeOut(300, () => ToastUtils.showError('请求错诶,请重试'));
throw Error();
}
//
ref.read(doPaperBottomReviewMarksProvider.notifier).setState(ReviewMarksBottomBtnsEnum.DRAG);
//
ref.read(drawMarkingProvider.notifier).setState(DrawMarkingVal([], []));
currentQuestion = result.data;
if (temTab != null) {
result.data!.scoreInterval = temTab.scoreInterval ?? 1;
MarkingZoom? markingZoom = await UseZoomImageHistoryUtils.getZoomImageInfo(
widget.markingUserId.toString() + '-' + (currentQuestion?.questionNum.toString() ?? ''));
MarkingZoom? markingZoom =
await UseZoomImageHistoryUtils.getZoomImageInfo(widget.markingUserId.toString() + '-' + (currentQuestion?.questionNum.toString() ?? ''));
if (markingZoom != null) {
imageScale = double.parse(markingZoom.scale.toStringAsFixed(2));
imagePosition = Offset(
@ -1156,60 +1189,8 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
imageScale = 1;
imagePosition = Offset(0, 0);
}
/** */
// int? thetypeNum = tabParams.type;
// // || _currentTab?.total == 0 total没有更新造成了total是0
// if (tabQuestionNum != null || _currentTab?.total == 0)
// await getTabsData(updateCurrentTag: true); // tag更新当前Tag数据
// currentQuestion?.scoreInterval = temTab.scoreInterval!;
// if (oldCurrentQuestion == null ||
// (oldCurrentQuestion.markingUserDetailId != currentQuestion!.markingUserDetailId)) {
// if (theExamIndex == 0 || tabQuestionNum != null) {
// // !tabParams.excessContinue
// theExamIndex = (temTab.finishCount >= temTab.total && temTab.excessCount <= 0) ||
// (!tabParams.excessContinue && currentQuestion!.isFinish)
// ? temTab.finishCount
// : temTab.finishCount + 1; //
// } else if (thetypeNum != null) {
// thetypeNum == 0 ? ++theExamIndex : --theExamIndex;
// }
// }
// theExamIndex = currentQuestion?.currentIndex ?? 0;
/**后端返回当前试题位置不需要前端再去计算位置了 不需要判断超量题和平均量了 */
// currentQuestion!.setTotalCountAndCurrentIndex(
// temTab.isExcess
// ? (temTab.total > temTab.excessAvgCount ? temTab.total : temTab.excessAvgCount)
// : temTab.total,
// temTab.finishCount); //
// currentQuestion?.totalCount = temTab.total;
}
/**
toUpState(setState, () {
bool hasSub = currentQuestion!.subQuestionDetailList.isNotEmpty;
activeQuestIndex = 0; //
double fullScore;
double getScore;
if (hasSub) {
SubQuestions questions = currentQuestion!.subQuestionDetailList[activeQuestIndex];
bool isFinish = questions.isFinish;
fullScore = questions.subQuestionScore;
getScore = isFinish ? questions.subQuestionGotScore! : 0;
} else {
fullScore = currentQuestion!.totalScore;
bool isFinish = currentQuestion!.isFinish; //
getScore = isFinish ? currentQuestion!.score! : 0;
}
questScore = getScore == 0 ? '' : getScore.toString(); //
hasZeroPointFive = getScore >= fullScore || questScore.length > 1; // /
// inputKeyboardGuidePage = flagInputKeyboardGuidePage; //
}, mounted);*/
bool hasSub = currentQuestion!.subQuestionDetailList.isNotEmpty;
activeQuestIndex = 0; //
double fullScore;
@ -1232,8 +1213,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
if (firstComeIn) setTimeOut(2000, () => firstComeIn = false);
if (ref.read(markingSubtopicSwitchingProvider.notifier).state != activeQuestIndex) {
//
Future.delayed(
Duration.zero, () => ref.read(markingSubtopicSwitchingProvider.notifier).setVal(activeQuestIndex));
Future.delayed(Duration.zero, () => ref.read(markingSubtopicSwitchingProvider.notifier).setVal(activeQuestIndex));
}
if (currentQuestion != null && widget.markingtype == MarkingListType.EXCEPTIONAL) {
BaseStructureResult<ExceptionInfo> res = await client.getMarkingQuestionsErrorInfo(currentQuestion!.id);
@ -1250,6 +1230,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
}
}
Future.delayed(Duration.zero, () => annotationTips = false);
// getMarkingQuestionsErrorInfo
return currentQuestion;
} catch (e) {
@ -1435,8 +1416,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
bool isNormal = !widget.exceptional; //
bool notNextTest = data.nextId == 0; //
//
var pressedNextTest =
notNextTest ? null : () => easyThrottle('TestQuestionSwitch', () => refresh(isNext: true));
var pressedNextTest = notNextTest ? null : () => easyThrottle('TestQuestionSwitch', () => refresh(isNext: true));
bool notHasPreviousTest = data.prevId == 0;
/**
@ -1501,8 +1481,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
color: const Color.fromRGBO(148, 163, 182, 1),
),
),
if (_currentTab!.isExcess &&
_currentTab!.finishCount > _currentTab!.total)
if (_currentTab!.isExcess && _currentTab!.finishCount > _currentTab!.total)
Container(
margin: EdgeInsets.only(left: 4.w),
child: Row(
@ -1513,8 +1492,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
color: const Color.fromRGBO(148, 163, 182, 1),
),
quickText(
(_currentTab!.finishCount - _currentTab!.total)
.toString(),
(_currentTab!.finishCount - _currentTab!.total).toString(),
size: isBroadwise ? 18.sp : 14.sp,
color: Color.fromRGBO(251, 144, 84, 1),
),
@ -1540,19 +1518,16 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
),
),
SizedBox(width: 8.w),
if (model.hideQuestionId &&
model.screenDirection == ScreenDirection.HORIZONTAL_SCREEN)
if (model.hideQuestionId && model.screenDirection == ScreenDirection.HORIZONTAL_SCREEN)
InkWell(
onTap: () {
Clipboard.setData(ClipboardData(text: data.paperNum ?? ''))
.then((value) {
Clipboard.setData(ClipboardData(text: data.paperNum ?? '')).then((value) {
ToastUtils.showSuccess('试卷编号已复制');
});
},
child: Row(
children: [
quickText('试卷编号: ',
size: 16.sp, color: const Color.fromRGBO(148, 163, 182, 1)),
quickText('试卷编号: ', size: 16.sp, color: const Color.fromRGBO(148, 163, 182, 1)),
quickText(
data.paperNum ?? '',
size: 16.sp,
@ -1585,8 +1560,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
color: const Color.fromRGBO(4, 201, 208, 1),
),
),
if (isBroadwise && widget.markingtype == MarkingListType.EXCEPTIONAL ||
data.isException)
if (isBroadwise && widget.markingtype == MarkingListType.EXCEPTIONAL || data.isException)
Container(
padding: EdgeInsets.symmetric(horizontal: 2.w, vertical: 2.h),
color: const Color.fromRGBO(245, 108, 108, 0.236),
@ -1630,18 +1604,14 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
size: isBroadwise ? 15.sp : 12.sp,
),
SizedBox(width: 1.w),
quickText('继续阅卷',
color: const Color.fromRGBO(80, 87, 103, 1),
size: isBroadwise ? 15.sp : 12.sp),
quickText('继续阅卷', color: const Color.fromRGBO(80, 87, 103, 1), size: isBroadwise ? 15.sp : 12.sp),
],
),
),
SizedBox(width: 10.w),
InkWell(
onTap: () {
ref
.read(ratingProgressProvider.notifier)
.setState(EndDrawerViewEnum.REVIEW_RECORD);
ref.read(ratingProgressProvider.notifier).setState(EndDrawerViewEnum.REVIEW_RECORD);
scaffoldKey.currentState?.openEndDrawer();
},
child: Row(
@ -1652,9 +1622,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
size: isBroadwise ? 15.sp : 12.sp,
),
SizedBox(width: 1.w),
quickText('阅卷记录',
color: const Color.fromRGBO(80, 87, 103, 1),
size: isBroadwise ? 15.sp : 12.sp),
quickText('阅卷记录', color: const Color.fromRGBO(80, 87, 103, 1), size: isBroadwise ? 15.sp : 12.sp),
],
),
),
@ -1666,9 +1634,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
),
InkWell(
onTap: () {
ref
.read(ratingProgressProvider.notifier)
.setState(EndDrawerViewEnum.RATING_PROGRESS);
ref.read(ratingProgressProvider.notifier).setState(EndDrawerViewEnum.RATING_PROGRESS);
scaffoldKey.currentState?.openEndDrawer();
},
child: Row(
@ -1679,9 +1645,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
size: isBroadwise ? 15.sp : 12.sp,
),
SizedBox(width: 1.w),
quickText('评分进度',
color: const Color.fromRGBO(80, 87, 103, 1),
size: isBroadwise ? 15.sp : 12.sp),
quickText('评分进度', color: const Color.fromRGBO(80, 87, 103, 1), size: isBroadwise ? 15.sp : 12.sp),
],
),
),
@ -1690,8 +1654,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
InkWell(
onTap: () {
if (data.isException) {
return ToastUtils.getFluttertoast(
context: context, msg: '当前试题已为异常题,无需重复提交');
return ToastUtils.getFluttertoast(context: context, msg: '当前试题已为异常题,无需重复提交');
}
toUpState(setState, () => showAbnormal = true, mounted);
},
@ -1817,17 +1780,14 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
return InkWell(
onTap: () {
double? getScore = quest.subQuestionGotScore;
ref
.read(markingSubtopicSwitchingProvider.notifier)
.setVal(index);
ref.read(markingSubtopicSwitchingProvider.notifier).setVal(index);
toUpState(setState, () {
activeQuestIndex = index;
// TODO
// pictureOverviewKey.currentState?.jumpToPage(activeQuestIndex);
questScore = getScore?.toString() ?? '';
hasZeroPointFive =
questScore != '' && getScore! >= quest.subQuestionScore;
hasZeroPointFive = questScore != '' && getScore! >= quest.subQuestionScore;
}, mounted);
},
child: Container(
@ -1848,8 +1808,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
alignment: const FractionalOffset(0.5, 1.78),
children: [
Container(
padding: EdgeInsets.symmetric(
horizontal: 4.w, vertical: 8.h),
padding: EdgeInsets.symmetric(horizontal: 4.w, vertical: 8.h),
alignment: Alignment.center,
decoration: BoxDecoration(
color: !activeIndex
@ -1871,9 +1830,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: activeIndex
? Colors.white
: const Color.fromRGBO(80, 87, 103, 1),
color: activeIndex ? Colors.white : const Color.fromRGBO(80, 87, 103, 1),
fontSize: 13.sp,
fontWeight: FontWeight.w500,
),
@ -1884,22 +1841,18 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
child: quickText(
'(${getDoubleRemoveZero(data.subQuestionDetailList[index].subQuestionScore)})',
size: 11.sp,
color: activeIndex
? Colors.white
: const Color.fromRGBO(
80, 87, 103, 1)),
color:
activeIndex ? Colors.white : const Color.fromRGBO(80, 87, 103, 1)),
)
],
)),
if (activeIndex)
Icon(Icons.arrow_drop_down_outlined,
color: const Color.fromRGBO(46, 91, 255, 1),
size: 20.sp)
color: const Color.fromRGBO(46, 91, 255, 1), size: 20.sp)
],
),
Container(
padding:
EdgeInsets.symmetric(horizontal: 4.w, vertical: 8.h),
padding: EdgeInsets.symmetric(horizontal: 4.w, vertical: 8.h),
alignment: Alignment.center,
child: Text(
getDoubleRemoveZero(quest.subQuestionGotScore, '请评分'),
@ -1945,8 +1898,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
),
child: Text(
'>>',
style:
TextStyle(color: Theme.of(context).primaryColor, fontSize: 12.sp),
style: TextStyle(color: Theme.of(context).primaryColor, fontSize: 12.sp),
),
)),
onHorizontalDragEnd: (detail) {
@ -1962,9 +1914,10 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
children: [
//
Container(
margin: EdgeInsets.only(top: 6.h),
// margin: EdgeInsets.only(top: 6.h),
padding: EdgeInsets.symmetric(horizontal: 1.w),
child: PictureOverview(
data: data,
questionNum: data.questionNum,
markingUserId: widget.markingUserId,
key: pictureOverviewKey,
@ -1973,21 +1926,14 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
annotationsFlag: annotationSwitch,
commentImageMap: data.commentImageUrlMap,
testQuestionNumber: widget.markingUserId.toString() + '-' + data.questionNum,
imageItems: data.getImageData(),
imageItems: data.studentAnswerList,
callAnnotationTips: () {
//
annotationTips = true;
},
),
),
//
// if (!showSetingFlag &&
// !widget.exceptional &&
// currentQuestion != null &&
// annotationsFlag &&
// !showAbnormal &&
// !showStandardAnswer)
// Positioned(
// left: 0,
// bottom: 0,
// child: BottomAnnotationSwitch(maxWidth: maxWidth - 1.5.w),
// ),
//
if (!hasSubtopic)
Positioned(
@ -2000,10 +1946,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
color: data.isException ? Colors.red : const Color.fromRGBO(46, 91, 255, 1),
child: Container(
padding: EdgeInsets.symmetric(
horizontal: (data.score == null ||
(getDoubleRemoveZero(data.score ?? 0)).length >= 2)
? 4.w
: 12.w,
horizontal: (data.score == null || (getDoubleRemoveZero(data.score ?? 0)).length >= 2) ? 4.w : 12.w,
vertical: 6.h),
alignment: Alignment.center,
child: Text(
@ -2029,15 +1972,11 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
color: data.isException ? Colors.red : const Color.fromRGBO(46, 91, 255, 1),
child: Container(
padding: EdgeInsets.symmetric(
horizontal: (data.score == null ||
(getDoubleRemoveZero(data.score ?? 0)).length >= 2)
? 4.w
: 12.w,
horizontal: (data.score == null || (getDoubleRemoveZero(data.score ?? 0)).length >= 2) ? 4.w : 12.w,
vertical: 6.h),
alignment: Alignment.center,
child: Text(
getDoubleRemoveZero(data.score,
'请评分,满分${getDoubleRemoveZero(currentQuestion?.totalScore)}'),
getDoubleRemoveZero(data.score, '请评分,满分${getDoubleRemoveZero(currentQuestion?.totalScore)}'),
style: TextStyle(
fontSize: 18.sp,
color: const Color.fromRGBO(46, 91, 255, 1),
@ -2047,26 +1986,23 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
),
),
//
if (widget.markingtype != MarkingListType.EXCEPTIONAL &&
!_theOldAnnotationGraffiti &&
!notHasPreviousTest)
if (widget.markingtype != MarkingListType.EXCEPTIONAL && !_theOldAnnotationGraffiti && !notHasPreviousTest)
Positioned(
left: 3.w,
top: ScreenUtil().setHeight(MediaQuery.of(context).size.height) / 2 * 0.87,
child: FloatingActionButton(
tooltip: '前往上一题',
backgroundColor: notHasPreviousTest
? const Color.fromRGBO(24, 32, 32, 0.04)
: const Color.fromRGBO(24, 32, 32, 0.1),
backgroundColor:
notHasPreviousTest ? const Color.fromRGBO(24, 32, 32, 0.04) : const Color.fromRGBO(24, 32, 32, 0.1),
focusColor: Theme.of(context).primaryColor,
elevation: 0,
onPressed: notHasPreviousTest
? null
: () => easyThrottle('TestQuestionSwitch', () => refresh()),
onPressed: notHasPreviousTest ? null : () => easyThrottle('TestQuestionSwitch', () => refresh()),
child: const Icon(Icons.arrow_back_ios, color: Colors.white),
heroTag: 'other',
),
),
//
DoPaperBottomReviewMarks(),
//
if (!_theOldAnnotationGraffiti && pressedNextTest != null && isNormal)
Positioned(
@ -2075,9 +2011,8 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
child: FloatingActionButton(
elevation: 0,
tooltip: '点击前往下一题',
backgroundColor: notNextTest
? const Color.fromRGBO(24, 32, 32, 0.04)
: const Color.fromRGBO(24, 32, 32, 0.1),
backgroundColor:
notNextTest ? const Color.fromRGBO(24, 32, 32, 0.04) : const Color.fromRGBO(24, 32, 32, 0.1),
foregroundColor: Colors.white,
onPressed: pressedNextTest,
child: const Icon(Icons.arrow_forward_ios, color: Colors.white),
@ -2169,8 +2104,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
//
$AbnormalBox(
businessHandle: (bool flag, String? reasonKey, String? otherReasons) =>
initiateException(flag, reasonKey, otherReasons),
businessHandle: (bool flag, String? reasonKey, String? otherReasons) => initiateException(flag, reasonKey, otherReasons),
isBroadwise: isBroadwise,
showAbnormal: !showAbnormal,
),
@ -2202,8 +2136,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
eventFireSub(model: SwitchKeyboardToReloadImages(true));
});
ref.read(annotationGraffitiSwitchProvider.notifier).setSwitch(false);
ToastUtils.showSuccess(newOpenAuxiliary ? '开启双栏打分' : '关闭双栏打分',
duration: const Duration(milliseconds: 300));
ToastUtils.showSuccess(newOpenAuxiliary ? '开启双栏打分' : '关闭双栏打分', duration: const Duration(milliseconds: 300));
});
},
// 线
@ -2212,8 +2145,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
width: isBroadwise ? 18.w : 42.w,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius:
BorderRadius.only(topLeft: Radius.circular(8.w), bottomLeft: Radius.circular(8.w)),
borderRadius: BorderRadius.only(topLeft: Radius.circular(8.w), bottomLeft: Radius.circular(8.w)),
color: Theme.of(context).primaryColor,
),
child: Row(
@ -2247,8 +2179,7 @@ class _MarkingPapersState extends ConsumerState<DoPapers>
tabName: _currentTab?.questionNum ?? '',
tabs: _currentTabs,
direction: keyboardModel?.screenDirection ?? ScreenDirection.HORIZONTAL_SCREEN,
call: (int detailId, String selectedQuesiontNum) =>
refresh(theId: detailId, theQuestionNum: selectedQuesiontNum),
call: (int detailId, String selectedQuesiontNum) => refresh(theId: detailId, theQuestionNum: selectedQuesiontNum),
markingUserId: widget.markingUserId,
questionNum: _currentTab?.questionNum,
),
@ -2429,10 +2360,8 @@ Widget $abnormalBox(
child: TextField(
controller: controller,
textInputAction: TextInputAction.next,
onEditingComplete: () => easyThrottle(
'Abnormal_submission_confirmation_button',
() => _useAbnormal.submit(context, controller,
(reasonType, reason) => businessHandle(true, reasonType, reason))),
onEditingComplete: () => easyThrottle('Abnormal_submission_confirmation_button',
() => _useAbnormal.submit(context, controller, (reasonType, reason) => businessHandle(true, reasonType, reason))),
maxLines: 15,
keyboardType: TextInputType.multiline,
decoration: InputDecoration(
@ -2452,8 +2381,7 @@ Widget $abnormalBox(
mainAxisAlignment: MainAxisAlignment.center,
children: [
InkWell(
onTap: () => easyThrottle(
'Abnormal_submission_confirmation_button', () => businessHandle(false, null, null)),
onTap: () => easyThrottle('Abnormal_submission_confirmation_button', () => businessHandle(false, null, null)),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h),
margin: EdgeInsets.only(right: 16.w),
@ -2483,8 +2411,7 @@ Widget $abnormalBox(
InkWell(
onTap: () => easyThrottle(
'Abnormal_submission_confirmation_button',
() => _useAbnormal.submit(
context, controller, (reasonType, reason) => businessHandle(true, reasonType, reason)),
() => _useAbnormal.submit(context, controller, (reasonType, reason) => businessHandle(true, reasonType, reason)),
),
// () {
@ -2582,8 +2509,7 @@ class StandardAnswerRegion extends StatelessWidget {
///
@hwidget
Widget $abnormalQuestionInfo(
{required bool hasSubtopic, required bool isBroadwise, required bool show, double? score, ExceptionInfo? info}) {
Widget $abnormalQuestionInfo({required bool hasSubtopic, required bool isBroadwise, required bool show, double? score, ExceptionInfo? info}) {
final _useFlagAnimation = useState(true);
AnimationController _useAnimationHorizontal = useAnimationController(
initialValue: 300,
@ -2675,14 +2601,12 @@ Widget $abnormalQuestionInfo(
Row(
children: [
if ((info?.studentName.length ?? 0) > 0)
quickText('考生:${info!.studentName}',
color: const Color.fromRGBO(104, 104, 113, 1), size: 14.sp
quickText('考生:${info!.studentName}', color: const Color.fromRGBO(104, 104, 113, 1), size: 14.sp
// overflow: TextOverflow.clip,
),
SizedBox(width: 3.w),
if ((info?.studentExamNum.length ?? 0) > 0)
quickText('考号:${info!.studentExamNum}',
color: const Color.fromRGBO(104, 104, 113, 1), size: 14.sp
quickText('考号:${info!.studentExamNum}', color: const Color.fromRGBO(104, 104, 113, 1), size: 14.sp
// overflow: TextOverflow.clip,
),
],
@ -2716,8 +2640,7 @@ Widget $abnormalQuestionInfo(
///
@hwidget
Widget $arbitrationQuestionInfo(
{required bool show, required bool isBroadwise, required bool hasSubtopic, required List<HistoricalScoring> data}) {
Widget $arbitrationQuestionInfo({required bool show, required bool isBroadwise, required bool hasSubtopic, required List<HistoricalScoring> data}) {
final _useFlagAnimation = useState(true);
AnimationController _useAnimationHorizontal = useAnimationController(
initialValue: 300,

View File

@ -0,0 +1,13 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:marking_app/common/model/enum/review_marks_bottom_btns_enum.dart';
//
final doPaperBottomReviewMarksProvider = StateNotifierProvider<DoPaperBottomReviewMarksHandle, ReviewMarksBottomBtnsEnum>(
(ref) => DoPaperBottomReviewMarksHandle(ReviewMarksBottomBtnsEnum.DRAG),
);
class DoPaperBottomReviewMarksHandle extends StateNotifier<ReviewMarksBottomBtnsEnum> {
DoPaperBottomReviewMarksHandle(ReviewMarksBottomBtnsEnum val) : super(val);
void setState(ReviewMarksBottomBtnsEnum val) => state = val;
}

View File

@ -0,0 +1,33 @@
/*
* @Author: wangyang 1147192855@qq.com
* @Date: 2022-07-14 18:16:06
* @LastEditors: wangyang 1147192855@qq.com
* @LastEditTime: 2022-08-01 16:17:33
* @FilePath: \marking_app\lib\provider\user_provider.dart
* @Description: APP上传文件状态
*/
import 'dart:ui';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import '../../../components/PictureOverview.dart';
//
final drawMarkingProvider =
StateNotifierProvider<DrawMarkingProviderHandle, DrawMarkingVal>((ref) => DrawMarkingProviderHandle(DrawMarkingVal([], [])));
class DrawMarkingProviderHandle extends StateNotifier<DrawMarkingVal> {
DrawMarkingProviderHandle(DrawMarkingVal val) : super(val);
void setState(DrawMarkingVal val) {
state = val;
}
}
class DrawMarkingVal {
List<GestureRecording> data;
List<Offset?> offsets;
DrawMarkingVal(this.data, this.offsets);
}

View File

@ -0,0 +1,198 @@
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:marking_app/common/mixin/common.dart';
import 'package:marking_app/common/model/common/base_structure_result.dart';
import 'package:marking_app/provider/user_provider.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/const_text.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';
class LogOff extends StatefulHookConsumerWidget {
const LogOff({Key? key}) : super(key: key);
@override
ConsumerState<LogOff> createState() => _LogOffState();
}
class _LogOffState extends ConsumerState<LogOff> with CommonMixin{
bool canClick = true;
bool readAgreement = false; //
logOff() async{
if (!canClick) return;
setState(() => canClick = false);
void toMsg(msg) {
ToastUtils.showError(msg);
setState(() => canClick = true);
}
if (!readAgreement) return toMsg('请勾选我已阅读用户协议和隐私协议');
final userState = ref.watch(userProvider);
EasyLoading.show(status: 'loading...');
RestClient client = await getClientLogin();
BaseStructureResult<dynamic> resultData = await client.getLogOff(userState.loginName);
if (resultData.code != 200) {
return ToastUtils.showError(resultData.message ?? '注销失败,请重试');
}
EasyLoading.dismiss();
ToastUtils.showSuccess('注销成功');
//
RouterManager.router.navigateTo(context, RouterManager.loginPath);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color.fromRGBO(248, 248, 248, 1),
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'注销',
style: TextStyle(fontSize: 14.sp, color: Color(0xFF333333)),
),
centerTitle: true,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios, color: Colors.black),
onPressed: () => Navigator.of(context).pop(),
),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 30.r,
),
Center(
child: Text(
'温馨提示,请仔细阅读',
style: TextStyle(
fontSize: 16.sp,
color: Color(0xFF464646),
fontWeight: FontWeight.w500),
),
),
SizedBox(
height: 20.r,
),
cont('您仅可注销您本人申请的账号'),
cont('注销后,账号的全部权益将被清除'),
cont('注销后,账号下的所有数据、记录等将无法访问或找回'),
cont('注销后,将清除该账号在网站保留的个人信息'),
cont('注销账号(账号删除)属于用户自主行为'),
/* Padding(
padding: EdgeInsets.symmetric(vertical: 5.r, horizontal: 14.r),
child: Row(
children: [
Text(
'注销账号即表示您已确认并同意',
style: TextStyle(fontSize: 14.sp, color: Color(0xFF616161)),
),
InkWell(
onTap: (){
RouterManager.router.navigateTo(
context,
'${RouterManager.agreementPath}?type=${AGREEMENT_KEY.USER_LOGOUT.name}',
transition: getTransition(),
);
},
child: Text(
'注销协议',
style: TextStyle(fontSize: 14.sp, color: Color(0xFF6888FD)),
),
)
],
),
),*/
SizedBox(
height: 50.r,
),
InkWell(
onTap:logOff,
child: Center(
child: Container(
margin: EdgeInsets.symmetric(vertical: 10.h),
alignment: Alignment.center,
width: 200.r,
height: 50.r,
decoration: BoxDecoration(
color: canClick
? const Color.fromRGBO(9, 105, 246, 1)
: Colors.grey,
/*boxShadow: [
BoxShadow(
color: const Color.fromRGBO(46, 91, 255, 0.5),
offset: Offset(6.w, 10.h), //y轴偏移量
blurRadius: 14, //
spreadRadius: 0.5, //
)
],*/
borderRadius: BorderRadius.all(
Radius.circular(20.w),
),
),
child: Text(
'确认注销',
style: TextStyle(fontSize: 16.sp, color: Colors.white),
),
),
),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 5.r, horizontal: 14.r),
child: Row(
children: [
Container(
width: 30.w,
padding: EdgeInsets.only(right: 10.w),
child: Checkbox(
activeColor: Colors.deepOrangeAccent,
checkColor: Colors.white,
value: readAgreement,
onChanged: (value) {
setState(() {
readAgreement = value ?? false;
});
},
),
),
Text(
'已确认并同意',
style: TextStyle(fontSize: 14.sp, color: Color(0xFF616161)),
),
InkWell(
onTap: () {
RouterManager.router.navigateTo(
context,
'${RouterManager.agreementPath}?type=${AGREEMENT_KEY.USER_LOGOUT.name}',
transition: getTransition(),
);
},
child: quickText(
'《注销协议》',
size: 12.sp,
color: Colors.deepOrangeAccent,
),
),
],
),
),
],
),
);
}
}
Widget cont(String name) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 5.r, horizontal: 14.r),
child: Text(
name,
style: TextStyle(fontSize: 14.sp, color: Color(0xFF616161)),
),
);
}

View File

@ -1,11 +1,14 @@
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:marking_app/common/mixin/common.dart';
import 'package:marking_app/common/model/common/base_structure_result.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/const_text.dart';
import 'package:marking_app/utils/fluro/index.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:package_info/package_info.dart';
//
@ -16,12 +19,14 @@ class OhterPage extends StatefulWidget {
State<OhterPage> createState() => _OhterPageState();
}
class _OhterPageState extends State<OhterPage> {
class _OhterPageState extends State<OhterPage> with CommonMixin{
String localVersion = '';
bool showLogOff = false;
@override
void initState() {
super.initState();
getShowLogOff();
getPageInfo();
}
@ -31,6 +36,16 @@ class _OhterPageState extends State<OhterPage> {
toUpState(setState, () => localVersion = packageInfo.version, mounted);
}
getShowLogOff() async{
RestClient client = await getClientLogin();
BaseStructureResult<dynamic> resultData = await client.showLogOff();
if(resultData.success){
setState(() {
showLogOff = resultData.data;
});
}
}
@override
Widget build(BuildContext context) {
final personalInfoTitleStly = TextStyle(
@ -56,7 +71,7 @@ class _OhterPageState extends State<OhterPage> {
Container(
margin: EdgeInsets.symmetric(vertical: 22.h, horizontal: 16.w),
padding: EdgeInsets.symmetric(vertical: 22.h, horizontal: 16.w),
height: 130.h,
height: showLogOff?250.h:200.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(6.w)),
color: Colors.white,
@ -85,7 +100,7 @@ class _OhterPageState extends State<OhterPage> {
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('用户隐私协议', style: personalInfoTitleStly),
Text('隐私政策', style: personalInfoTitleStly),
Icon(
Icons.arrow_forward_ios,
color: const Color.fromRGBO(80, 87, 103, 1),
@ -99,11 +114,67 @@ class _OhterPageState extends State<OhterPage> {
height: 1.w,
color: const Color.fromRGBO(240, 243, 255, 1),
),
SizedBox(height: 8.h),
InkWell(
onTap: () {
RouterManager.router.navigateTo(
context,
transition: TransitionType.fadeIn,
'${RouterManager.agreementPath}?type=${AGREEMENT_KEY.USER_AGREEMENT.name}',
);
},
child: Container(
padding: EdgeInsets.only(bottom: 4.h),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('用户协议', style: personalInfoTitleStly),
Icon(
Icons.arrow_forward_ios,
color: const Color.fromRGBO(80, 87, 103, 1),
size: 16.sp,
)
],
),
),
),
Container(
height: 1.w,
color: const Color.fromRGBO(240, 243, 255, 1),
),
// SizedBox(height: 8.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [Text('APP版本', style: personalInfoTitleStly), quickText(localVersion)],
)
),
Container(
height: 1.w,
color: const Color.fromRGBO(240, 243, 255, 1),
),
// SizedBox(height: 8.h),
if(showLogOff)
InkWell(
onTap: () {
RouterManager.router.navigateTo(
context,
RouterManager.logOffPath
);
},
child: Container(
padding: EdgeInsets.only(bottom: 4.h,top: 8.r),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('注销账号', style: personalInfoTitleStly),
Icon(
Icons.arrow_forward_ios,
color: const Color.fromRGBO(80, 87, 103, 1),
size: 16.sp,
)
],
),
),
),
],
),
),

View File

@ -0,0 +1,291 @@
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:marking_app/common/config/request_config.dart';
import 'package:marking_app/common/mixin/common.dart';
import 'package:marking_app/common/model/common/base_structure_result.dart';
import 'package:marking_app/common/model/user/user_login_params.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/common_utils.dart';
import 'package:marking_app/utils/const_text.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';
class Register extends StatefulWidget {
const Register({Key? key}) : super(key: key);
@override
State<Register> createState() => _RegisterState();
}
class _RegisterState extends State<Register> with CommonMixin {
late final FocusNode _theFocus;
late final FocusNode _pwdFocus; //
//
late final TextEditingController _userNameController;
late final TextEditingController _passwordController;
bool readAgreement = false; //
bool _isShowPwd = true;
bool canLogin = true;
@override
void initState() {
super.initState();
_userNameController = TextEditingController();
_passwordController = TextEditingController();
_pwdFocus = FocusNode();
_theFocus = FocusNode();
}
@override
void dispose() {
super.dispose();
_userNameController.dispose();
_passwordController.dispose();
_pwdFocus.dispose();
_theFocus.dispose();
}
void toRegister() async {
if (!canLogin) return;
setState(() => canLogin = false);
void toMsg(msg) {
ToastUtils.showError(msg);
setState(() => canLogin = true);
}
FocusScope.of(context).requestFocus(_theFocus);
try {
String userName = _userNameController.text.trim();
String userPwd = _passwordController.text.trim();
if (userName == '') return toMsg('请填写用户账号');
if (userPwd == '') return toMsg('请填写密码');
if (!readAgreement) return toMsg('请勾选我已阅读用户协议和隐私协议');
String userPwdMd5 = CommonUtils.generateMD5(userPwd);
print('注册userPwdMd5=$userPwdMd5');
EasyLoading.show(status: 'loading...');
RestClient client = await getClientLogin();
BaseStructureResult<dynamic> resultData = await client.toRegister(UserLoginParams(userName, userPwdMd5, 0));
if (resultData.code != 200) {
return toMsg(resultData.message ?? '注册失败,请重试');
}
ToastUtils.showSuccess('注册成功,请登录');
//
RouterManager.router.navigateTo(context, RouterManager.loginPath);
} finally {
EasyLoading.dismiss();
}
}
void _showPassword() {
setState(() {
_isShowPwd = !_isShowPwd;
});
}
@override
Widget build(BuildContext context) {
return GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
FocusScope.of(context).requestFocus(_theFocus);
},
child: AnnotatedRegion(
value: const SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
systemNavigationBarIconBrightness: Brightness.light,
statusBarIconBrightness: Brightness.light,
statusBarBrightness: Brightness.dark,
),
child: Scaffold(
backgroundColor: Colors.transparent,
resizeToAvoidBottomInset: false,
body: Stack(
children: [
Container(
width: double.infinity,
height: double.infinity,
alignment: Alignment.center,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/login_bgi.png'),
fit: BoxFit.fill, //
),
),
child: SingleChildScrollView(
child: Column(
children: [
Container(
width: 86.w,
height: 86.w,
alignment: Alignment.center,
child: SizedBox(
height: 86.w,
width: 86.w,
child: Image.asset('assets/images/logo.png', fit: BoxFit.cover),
),
),
Container(
margin: EdgeInsets.symmetric(horizontal: 32.w, vertical: 24.h),
padding: EdgeInsets.only(top: 34.h, bottom: 16.h, left: 22.w, right: 22.w),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(width: 1.w, color: Colors.white),
borderRadius: BorderRadius.all(Radius.circular(10.w)),
boxShadow: const [
BoxShadow(
color: Color.fromRGBO(46, 91, 255, 0.1),
offset: Offset.zero, //y轴偏移量
blurRadius: 100, //
spreadRadius: 100, //
)
],
),
child: Column(children: [
TextField(
controller: _userNameController,
maxLines: 1,
maxLength: 20,
textInputAction: TextInputAction.next,
onEditingComplete: () {
FocusScope.of(context).requestFocus(_pwdFocus);
},
style: TextStyle(
color: const Color.fromRGBO(80, 87, 103, 1),
fontSize: 15.sp,
),
decoration: InputDecoration(
hintText: "请输入账号",
hintStyle: TextStyle(fontSize: 16.sp, color: const Color.fromRGBO(153, 153, 153, 1)),
labelText: "账号",
labelStyle: TextStyle(fontSize: 16.sp, color: const Color.fromRGBO(148, 163, 182, 1)),
),
),
TextField(
focusNode: _pwdFocus,
controller: _passwordController,
keyboardType: TextInputType.number,
maxLines: 1,
obscureText: _isShowPwd, //
textInputAction: TextInputAction.go,
onSubmitted: (val) => toRegister(),
style: TextStyle(
color: const Color.fromRGBO(80, 87, 103, 1),
fontSize: 15.sp,
),
decoration: InputDecoration(
hintText: "请输入密码",
suffix: GestureDetector(
onTap: _showPassword,
child: Icon(
Icons.remove_red_eye,
color: !_isShowPwd ? Theme.of(context).primaryColor : Colors.grey,
),
),
hintStyle: TextStyle(fontSize: 16.sp, color: const Color.fromRGBO(153, 153, 153, 1)),
labelText: "密码",
isDense: true,
labelStyle: TextStyle(fontSize: 16.sp, color: const Color.fromRGBO(148, 163, 182, 1)),
),
),
SizedBox(
height: 12.h,
),
InkWell(
onTap: toRegister,
child: Container(
margin: EdgeInsets.symmetric(vertical: 10.h),
decoration: BoxDecoration(
color: canLogin ? const Color.fromRGBO(9, 105, 246, 1) : Colors.grey,
boxShadow: [
BoxShadow(
color: const Color.fromRGBO(46, 91, 255, 0.5),
offset: Offset(6.w, 10.h), //y轴偏移量
blurRadius: 14, //
spreadRadius: 0.5, //
)
],
borderRadius: BorderRadius.all(
Radius.circular(8.w),
),
),
alignment: Alignment.center,
width: double.infinity,
height: 50.h,
child: Text(
'注 册',
style: TextStyle(fontSize: 16.sp, color: Colors.white),
),
),
),
Row(
children: [
Container(
width: 30.w,
padding: EdgeInsets.only(right: 10.w),
child: Checkbox(
activeColor: Colors.deepOrangeAccent,
checkColor: Colors.white,
value: readAgreement,
onChanged: (value) {
FocusScope.of(context).requestFocus(_pwdFocus);
FocusScope.of(context).requestFocus(_theFocus);
setState(() {
readAgreement = value ?? false;
});
},
),
),
InkWell(
onTap: () {
RouterManager.router.navigateTo(
context,
'${RouterManager.agreementPath}?type=${AGREEMENT_KEY.USER_AGREEMENT.name}',
transition: getTransition(),
);
},
child: quickText('我已阅读', size: 11.sp),
),
InkWell(
onTap: () {
RouterManager.router.navigateTo(
context,
'${RouterManager.agreementPath}?type=${AGREEMENT_KEY.USER_AGREEMENT.name}',
transition: getTransition(),
);
},
child: quickText(
'《用户协议》',
size: 12.sp,
color: Colors.deepOrangeAccent,
),
),
],
),
]),
)
],
),
)),
Positioned(
top: MediaQuery.of(context).padding.top + 20.r,
left: 20.r,
child: InkWell(
onTap: () => Navigator.pop(context),
child: Icon(Icons.arrow_back_ios_new_rounded, color: Colors.white, size: 24.sp),
),
),
],
),
),
),
);
}
}

View File

@ -0,0 +1,499 @@
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:marking_app/common/mixin/common.dart';
import 'package:marking_app/common/model/common/base_structure_result_report.dart';
import 'package:marking_app/common/model/report/report_marking_detail.dart';
import 'package:marking_app/common/model/report/report_marking_detail.dart';
import 'package:marking_app/common/model/report/report_marking_detail_params.dart';
import 'package:marking_app/common/model/report/report_student_info.dart';
import 'package:marking_app/components/ReturnToHomepage.dart';
import 'package:marking_app/pages/report_detail/widgets/complete_table.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/easy_refresh/MyEmptyWidget.dart';
import 'package:marking_app/utils/request/rest_client_report.dart';
import 'widgets/custom_rect.dart';
class CompletedReport extends StatefulWidget {
final int examId;
final String studentNo;
const CompletedReport(
{Key? key, required this.examId, required this.studentNo})
: super(key: key);
@override
State<CompletedReport> createState() => _CompletedReportState();
}
class _CompletedReportState extends State<CompletedReport> with CommonMixin {
ReportStudentInfo? studentInfo;
int currentSubjectId = 0;
ExamOriginPapers? examOrigin;
List<ExamOriginPapers> examOriginList = [];
List<QuestionAnswers> questionAnswers = [];
final viewTransformationController = TransformationController();
bool isList = false;
@override
void initState() {
final zoomFactor = 0.5;
final xTranslate = 0.0;
final yTranslate = 0.0;
// final yTranslate = examOrigin!.width/2;
viewTransformationController.value.setEntry(0, 0, zoomFactor);
viewTransformationController.value.setEntry(1, 1, zoomFactor);
viewTransformationController.value.setEntry(2, 2, zoomFactor);
viewTransformationController.value.setEntry(0, 3, -xTranslate);
viewTransformationController.value.setEntry(1, 3, -yTranslate);
super.initState();
getInfo();
}
void getInfo() async {
EasyLoading.show(status: 'loading...');
RestClientReport clientReport = await getClientReport();
BaseStructureResultReport<ReportStudentInfo> res =
await clientReport.getStudentInfo(widget.examId, widget.studentNo);
if (res.success) {
setState(() {
studentInfo = res.data!;
currentSubjectId =
studentInfo!.subject.length > 0 ? studentInfo!.subject[0].value : 0;
getImageDetail();
});
} else {
EasyLoading.dismiss();
}
}
void getImageDetail() async {
RestClientReport clientReport = await getClientReport();
ReportMarkingDetailParams params =
ReportMarkingDetailParams(currentSubjectId, widget.studentNo);
BaseStructureResultReport<ReportMarkingDetail> res =
await clientReport.getMarkingDetail(params);
setState(() {
if (res.data != null) {
examOrigin = res.data!.examOriginPapers[0];
examOriginList = res.data!.examOriginPapers;
questionAnswers = res.data!.questionAnswers;
} else {
examOriginList = [];
examOrigin = null;
questionAnswers = [];
}
});
EasyLoading.dismiss();
}
@override
Widget build(BuildContext context) {
if (studentInfo == null) {
return Container();
}
return Scaffold(
backgroundColor: Color(0xFFEDF0FF),
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'${studentInfo!.userName}已完成考试报告',
style: TextStyle(fontSize: 14.r, color: Color(0xFF000000)),
),
centerTitle: true,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios, color: Colors.black),
onPressed: () => Navigator.of(context).pop(),
),
actions: [
ReturnToHomepage(),
InkWell(
onTap: () {
RouterManager.router.navigateTo(context,
'${RouterManager.reportHistoryPath}?classId=${studentInfo!.classId}&userId=${studentInfo!.userId}&studentName=${Uri.encodeComponent(studentInfo!.userName)}');
},
child: UnconstrainedBox(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 5.r),
margin: EdgeInsets.only(right: 14.r),
height: 22.r,
decoration: BoxDecoration(
border: Border.all(width: 1.r, color: Color(0xFF6988FD)),
borderRadius: BorderRadius.circular(5.r),
),
child: Center(
child: Text(
'历次成绩',
style: TextStyle(fontSize: 10.r, color: Color(0xFF6988FD)),
),
),
),
),
),
],
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(top: 10.r, left: 14.r, right: 14.r),
child: Text(
'${studentInfo!.userName}${studentInfo!.examName}',
style: TextStyle(
fontSize: 14.sp,
color: Color(0xFF6787FD),
fontWeight: FontWeight.w500),
),
),
Container(
margin: EdgeInsets.only(top: 10.r, left: 14.r, right: 14.r),
padding: EdgeInsets.symmetric(horizontal: 10.r),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
color: Colors.white,
boxShadow: [
BoxShadow(
color: const Color.fromRGBO(0, 0, 0, 0.1),
offset: Offset(0, 0), //y轴偏移量
blurRadius: 2, //
spreadRadius: 1, //
)
],
),
child: Column(
children: [
Container(
margin: EdgeInsets.only(top: 10.r),
width: double.infinity,
height: 30.r,
decoration: BoxDecoration(
color: Color(0xFFEFF1FF),
borderRadius: BorderRadius.all(Radius.circular(2.r))),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: List.generate(
studentInfo!.scoreInfo.length > 7
? 7
: studentInfo!.scoreInfo.length, (index) {
var item = studentInfo!.scoreInfo[index];
return Container(
width: (MediaQuery.of(context).size.width - 48.r) / 7,
child: _subjectText(item.text));
}),
),
),
Container(
width: double.infinity,
height: 30.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(2.r))),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: List.generate(
studentInfo!.scoreInfo.length > 7
? 7
: studentInfo!.scoreInfo.length, (index) {
var item = studentInfo!.scoreInfo[index];
return Container(
width: (MediaQuery.of(context).size.width - 48.r) / 7,
child: _subjectText(item.value.toString()));
}),
),
),
if (studentInfo!.scoreInfo.length > 7)
Container(
width: double.infinity,
height: 30.r,
decoration: BoxDecoration(
color: Color(0xFFEFF1FF),
borderRadius: BorderRadius.all(Radius.circular(2.r))),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: List.generate(studentInfo!.scoreInfo.length - 7,
(index) {
var item = studentInfo!.scoreInfo[index + 7];
return Container(
width:
(MediaQuery.of(context).size.width - 48.r) / 7,
child: _subjectText(item.text));
}),
),
),
if (studentInfo!.scoreInfo.length > 7)
Container(
width: double.infinity,
height: 30.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(2.r))),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: List.generate(studentInfo!.scoreInfo.length - 7,
(index) {
var subject = studentInfo!.scoreInfo[index + 7];
return Container(
width:
(MediaQuery.of(context).size.width - 48.r) / 7,
child: _subjectText(subject.value.toString()));
}),
),
),
],
),
),
SizedBox(
height: 10.r,
),
Expanded(
child: Stack(
children: [
Container(
margin: EdgeInsets.only(top: 10.r, left: 14.r, right: 14.r),
padding: EdgeInsets.symmetric(vertical: 15.r, horizontal: 10.r),
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
color: Colors.white,
boxShadow: [
BoxShadow(
color: const Color.fromRGBO(0, 0, 0, 0.1),
offset: Offset(0, 0), //y轴偏移量
blurRadius: 2, //
spreadRadius: 1, //
)
],
),
child: Column(
children: [
SizedBox(
height: 30.r,
width: MediaQuery.of(context).size.width,
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
Subject item = studentInfo!.subject[index];
return InkWell(
onTap: () {
setState(() {
currentSubjectId = item.value;
EasyLoading.show(status: 'loading...');
getImageDetail();
});
},
child: Container(
width: 30.r,
height: 30.r,
margin: EdgeInsets.only(
right: index == studentInfo!.subject.length
? 0
: (MediaQuery.of(context).size.width -
30.r * 9 -
104.r) /
8),
decoration: BoxDecoration(
color: currentSubjectId == item.value
? Color(0xFF6787FD)
: Color(0xFFFFFFFF),
shape: BoxShape.circle,
// borderRadius: BorderRadius.all(Radius.circular(13.r)),
),
child: Center(
child: Text(
item.text,
style: TextStyle(
fontSize: 11.sp,
color: currentSubjectId == item.value
? Colors.white
: Color(0xFF667095),
fontWeight: FontWeight.w400),
)),
),
);
},
itemCount: studentInfo!.subject.length,
scrollDirection: Axis.horizontal,
),
),
Expanded(
child: examOrigin != null && examOrigin!.imageUrl != ''
? !isList
? Padding(
padding: EdgeInsets.only(top: 5.r),
child: InteractiveViewer(
transformationController:
viewTransformationController,
constrained: false,
boundaryMargin: EdgeInsets.all(140.r),
minScale: 0.1,
//
maxScale: 4.0,
//
child: CustomRect(examOrigin!)),
)
: Padding(
padding: EdgeInsets.only(top: 10.r),
child: questionAnswers.length > 0
? CompleteTable(
fixedCols: 0,
fixedRows: 1,
bodyList: questionAnswers,
)
: MyEmptyWidget(),
)
: MyEmptyWidget(),
),
SizedBox(
height: 15.r,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
flex: 1,
child: InkWell(
onTap: () {
isList = false;
setState(() {});
},
child: Container(
height: 27.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
color: !isList
? Color(0xFF6988FD)
: Color(0xFFEDEFFF),
),
child: Center(
child: Text(
'查看原卷',
style: TextStyle(
fontSize: 12.sp,
color: !isList
? Colors.white
: Color(0xFF7B7B7E)),
),
),
),
),
),
SizedBox(
width: 20.r,
),
Flexible(
flex: 1,
child: InkWell(
onTap: () {
isList = true;
setState(() {});
},
child: Container(
height: 27.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
color: isList
? Color(0xFF6988FD)
: Color(0xFFEDEFFF),
),
child: Center(
child: Text(
'查看列题',
style: TextStyle(
fontSize: 12.sp,
color: isList
? Colors.white
: Color(0xFF7B7B7E)),
),
),
),
),
),
],
),
],
),
),
if (!isList)
Positioned(
left: 0.r,
top: MediaQuery.of(context).size.height / 4,
child: InkWell(
onTap: () {
var num = examOrigin!.pageIndex;
if (num > 1) {
setState(() {
examOrigin = examOriginList[num - 1 - 1];
});
}
},
child: Opacity(
opacity: examOrigin != null && examOrigin!.pageIndex > 1
? 1
: 0.3,
child: Image.asset(
'assets/images/report_left_icon.png',
width: 33.r,
height: 33.r,
)),
),
),
if (!isList)
Positioned(
right: 0,
top: MediaQuery.of(context).size.height / 4,
child: InkWell(
onTap: () {
var num = examOrigin!.pageIndex;
if (num < examOriginList.length) {
setState(() {
examOrigin = examOriginList[num];
});
}
},
child: Opacity(
opacity: examOrigin != null &&
examOrigin!.pageIndex < examOriginList.length
? 1
: 0.3,
child: Image.asset(
'assets/images/report_right_icon.png',
width: 33.r,
height: 33.r,
)),
/* Image.asset(
'assets/images/report_right_icon.png',
width: 33.r,
height: 33.r,
)*/
),
)
],
)),
SizedBox(
height: 10.r,
),
],
),
);
}
}
class _subjectText extends StatelessWidget {
final String name;
final bool isTitle;
const _subjectText(this.name, {this.isTitle = true, Key? key})
: super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: Text(
name,
style: TextStyle(
fontSize: isTitle ? 11.sp : 12.sp,
color: isTitle ? Color(0xFF667095) : Color(0xFF424242),
fontWeight: FontWeight.w400),
),
);
}
}

View File

@ -23,6 +23,7 @@ import 'package:marking_app/pages/report_detail/widgets/no_data.dart';
import 'package:marking_app/pages/report_detail/widgets/overall_level_table.dart';
import 'package:marking_app/pages/report_detail/widgets/report_card_dialog.dart';
import 'package:marking_app/pages/report_detail/widgets/question_table.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/request/rest_client_report.dart';
import 'package:marking_app/utils/toast_utils.dart';
@ -105,7 +106,6 @@ class _ReportDetailState extends ConsumerState<ReportDetail> with CommonMixin {
BaseStructureResultReport<DetailBaseInfo> result =
await clientReport.getReportDetail(widget.examId,
widget.showGrade && isGrade ? -1 : currentClass.value);
// print('*************result=${result.message}');
if (result.code == 200) {
setState(() {
currentPage = 1;
@ -139,9 +139,7 @@ class _ReportDetailState extends ConsumerState<ReportDetail> with CommonMixin {
limit: pageSize);
BaseStructureResultReport<SmallQuestion> res =
await clientReport.getQuestion(params);
print(
'res.data!.total=${res.code == 200 ? res.data!.bodyExcelData.sheets[0].bodyData.length : ''}');
if (res.code != 200 || res.data == null) {
if (res.code != 200 || res.data == null) {
setState(() {
smallQuestionRes = null;
questionTotalPage = 0;
@ -212,7 +210,10 @@ class _ReportDetailState extends ConsumerState<ReportDetail> with CommonMixin {
});
EasyLoading.dismiss();
}
goCompleteReport(BuildContext context, int index,{String studentNo = 'true'}){
RouterManager.router.navigateTo(context, '${RouterManager.completedReportPath}?examId=${widget.examId}&studentNo=${studentNo == 'true'?initialList[index].examStudentId:studentNo}');
}
//
void showAlertDialog(BuildContext context, int index) {
List<String> detailHead = [];
@ -518,6 +519,7 @@ class _ReportDetailState extends ConsumerState<ReportDetail> with CommonMixin {
isHtml:true,
fixedRows: 1,
fixedCols: 1,
showCardDetail: goCompleteReport,
),
)
: NoData(),
@ -540,6 +542,7 @@ class _ReportDetailState extends ConsumerState<ReportDetail> with CommonMixin {
isHtml:true,
fixedRows: 1,
fixedCols: 1,
showCardDetail: goCompleteReport,
),
),
Row(
@ -668,6 +671,8 @@ class _ReportDetailState extends ConsumerState<ReportDetail> with CommonMixin {
isScore: true,
fixedRows: 1,
fixedCols: 3,
showCardDetail: goCompleteReport,
smallQuestion:true,
),
)
: NoData(),
@ -797,7 +802,8 @@ class _ReportDetailState extends ConsumerState<ReportDetail> with CommonMixin {
child: CardList(
headList: cardHeadList,
bodyList: cardBodyList,
showCardDetail: showAlertDialog,
// showCardDetail: showAlertDialog,
showCardDetail: goCompleteReport,
fixedRows: 1,
fixedCols: 3,
),

View File

@ -1,15 +1,78 @@
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:functional_widget_annotation/functional_widget_annotation.dart';
import 'package:marking_app/common/mixin/common.dart';
import 'package:marking_app/common/model/common/base_structure_result_report.dart';
import 'package:marking_app/common/model/report/report_student_history_record.dart';
import 'package:marking_app/components/ReturnToHomepage.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/common_utils.dart';
import 'package:marking_app/utils/easy_refresh/MyEmptyWidget.dart';
import 'package:marking_app/utils/index.dart';
import 'package:marking_app/utils/request/rest_client_report.dart';
import 'package:syncfusion_flutter_datepicker/datepicker.dart';
part 'report_history.g.dart';
class ReportHistory extends StatefulWidget {
const ReportHistory({Key? key}) : super(key: key);
final int userId;
final int classId;
final String studentName;
const ReportHistory({Key? key, required this.classId, required this.userId, required this.studentName}) : super(key: key);
@override
State<ReportHistory> createState() => _ReportHistoryState();
}
class _ReportHistoryState extends State<ReportHistory> {
class _ReportHistoryState extends State<ReportHistory> with CommonMixin, TickerProviderStateMixin {
bool isWork = true;
String startDataTime = CommonUtils.getWeekStartDate().toString().substring(0, 10);
String endDataTime = CommonUtils.getWeekEndDate().toString().substring(0, 10);
String customTimeStr = '自定义';
late TabController tabController;
List<ReportStudentHistoryRecord> dataList = [];
late final EasyRefreshController refreshController;
@override
void initState() {
print('userId=${widget.userId}&classId=${widget.classId}');
super.initState();
refreshController = EasyRefreshController();
tabController = TabController(length: 3, vsync: this);
EasyLoading.show(status: 'loading...');
getList();
}
void getList() async {
if (startDataTime == DateTime.now().toString().substring(0, 10) || DateTime.parse(startDataTime).isAfter(DateTime.now())) {
DateTime now = DateTime.parse(startDataTime);
endDataTime = now.add(Duration(days: 1)).toString().substring(0, 10);
print(now.add(Duration(days: 1)));
} else {
endDataTime = DateTime.now().toString().substring(0, 10);
}
RestClientReport clientReport = await getClientReport();
BaseStructureResultReport<List<ReportStudentHistoryRecord>> res =
// 488491659239519, 488491659190341, '2023-03-08', '2024-04-19'
await clientReport.getStudentHistroyRecords(widget.userId, widget.classId, startDataTime, endDataTime);
if (res.success) {
setState(() {
dataList = res.data!;
});
}
EasyLoading.dismiss();
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
tabController.dispose();
}
@override
Widget build(BuildContext context) {
@ -18,7 +81,7 @@ class _ReportHistoryState extends State<ReportHistory> {
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'已完成报告',
'${widget.studentName}已完成考试报告',
style: TextStyle(fontSize: 14.r, color: Color(0xFF000000)),
),
centerTitle: true,
@ -26,10 +89,13 @@ class _ReportHistoryState extends State<ReportHistory> {
icon: Icon(Icons.arrow_back_ios, color: Colors.black),
onPressed: () => Navigator.of(context).pop(),
),
actions: [
ReturnToHomepage(),
],
),
body: Column(
children: [
Container(
/* Container(
width: MediaQuery.of(context).size.width * 0.8,
height: 40.r,
margin: EdgeInsets.only(
@ -89,9 +155,311 @@ class _ReportHistoryState extends State<ReportHistory> {
)),
],
),
)
),*/
SizedBox(
height: 10.r,
),
JobConditionFilter(
controller: tabController,
customTimeStr: customTimeStr,
customTime: tabController.index != 3 || ((endDataTime == null || endDataTime == '') && (startDataTime == null || startDataTime == ''))
? null
: PickerDateRange(
startDataTime == null || startDataTime == '' ? null : DateTime.parse(startDataTime!),
endDataTime == null || endDataTime == '' ? null : DateTime.parse(endDataTime!),
),
onTimeFilter: (String? startTime, String? endTime) {
if (startTime == null && endTime == null) {
if (tabController.index == 3) {
tabController.animateTo(0);
}
startDataTime = '';
endDataTime = '';
customTimeStr = '自定义';
} else {
EasyLoading.show(status: 'loading...');
startDataTime = startTime != null ? startTime : '';
endDataTime = endTime != null ? endTime : '';
setState(() {});
getList();
}
// _refreshController2.callRefresh();
},
refreshTime: (value) {
if (value != null && value.startDate != null) {
customTimeStr = value.startDate?.toString().substring(0, 10) ?? '';
setState(() {});
if (value.endDate != null) {
if (value.startDate!.year == value.endDate!.year) {
customTimeStr = value.startDate.toString().substring(5, 10) + '~${value.endDate.toString().substring(5, 10)}';
setState(() {});
} else {
customTimeStr = '$customTimeStr~${value.endDate?.toString().substring(0, 10)}';
setState(() {});
}
}
}
}),
Expanded(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 14.r, horizontal: 14.r),
child: EasyRefresh(
firstRefresh: false,
taskIndependence: true,
controller: refreshController,
header: MaterialHeader(),
footer: TaurusFooter(),
onRefresh: () async {
getList();
},
child: dataList.length > 0
? ListView.builder(
itemCount: dataList.length,
itemBuilder: (context, index) {
ReportStudentHistoryRecord item = dataList[index];
return InkWell(
onTap: () {
RouterManager.router
.navigateTo(context, '${RouterManager.completedReportPath}?examId=${item.examId}&studentNo=${item.studentExamNum}');
},
child: Container(
// padding: EdgeInsets.all(6.r),
margin: EdgeInsets.only(bottom: 10.r),
width: double.infinity,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/report_student_history_bg.png'),
fit: BoxFit.fill,
),
border: Border.all(width: 1.r, color: Color.fromRGBO(46, 91, 255, 0.2)),
borderRadius: BorderRadius.circular(5.r),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.symmetric(
vertical: 10.r,
horizontal: 10.r,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
item.examName,
style: TextStyle(fontSize: 12.sp, color: Color(0xFF000000)),
),
Spacer(),
Text(
item.examStartTime,
style: TextStyle(fontSize: 12.sp, color: Color(0xFF4A4A4A)),
)
],
),
),
SizedBox(
height: 2.r,
),
Container(
padding: EdgeInsets.symmetric(horizontal: 10.r),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.r),
),
child: item.scoreInfo.length > 0
? Scrollbar(
// thumbVisibility:true,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: List.generate(item.scoreInfo.length, (i) {
ScoreInfo score = item.scoreInfo[i];
return Row(
children: [
Column(
children: [
Container(
height: 22.r,
width: item.scoreInfo.length > 4
? 90.r
: (MediaQuery.of(context).size.width - 48.r - (item.scoreInfo.length - 1) * 1.5.r) /
item.scoreInfo.length,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: i == 0 ? Radius.circular(4.r) : Radius.zero,
topRight: i == item.scoreInfo.length - 1 ? Radius.circular(4.r) : Radius.zero),
color: Color(0xFFECECEC),
),
child: Center(
child: Text(
score.text,
style: TextStyle(fontSize: 12.sp, color: Color(0xFF8A8A8A)),
),
),
),
Container(
height: 30.r,
width: item.scoreInfo.length > 4
? 90.r
: (MediaQuery.of(context).size.width - 48.r - (item.scoreInfo.length - 1) * 1.5.r) /
item.scoreInfo.length,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: i == 0 ? Radius.circular(4.r) : Radius.zero,
bottomRight: i == item.scoreInfo.length - 1 ? Radius.circular(4.r) : Radius.zero),
color: Colors.white,
),
child: Center(
child: Text(
score.value.toString(),
style: TextStyle(fontSize: 12.sp, color: Color(0xFF4A4A4A)),
),
),
),
],
),
SizedBox(
width: i < item.scoreInfo.length - 1 ? 1.5.r : 0.r,
),
],
);
}),
),
),
)
: Center(
child: Text(
'-暂无数据-',
style: TextStyle(fontSize: 12.sp, color: Color(0xFF8A8A8A)),
)),
),
SizedBox(
height: 20.r,
),
],
),
),
);
})
: MyEmptyWidget(),
),
),
),
],
),
);
}
}
@hwidget
Widget jobConditionFilter(BuildContext context,
{required TabController controller,
PickerDateRange? customTime,
required Function refreshTime,
required String customTimeStr,
required Function(String? startTime, String? endTime) onTimeFilter}) {
var customTimeState = PickerDateRange(null, null);
if (customTime != null) {
customTimeState =
PickerDateRange(customTime!.startDate != null ? customTime!.startDate : null, customTime!.endDate != null ? customTime!.endDate : null);
}
DateTime getMonthStartDate() {
DateTime now = DateTime.now();
return DateTime(now.year, now.month, 1); //
}
DateTime getMonthEndDate() {
DateTime now = DateTime.now();
int nextMonth = now.month + 1;
if (nextMonth > 12) {
nextMonth = 1;
now = now.add(Duration(days: 31 - now.day)); //
} else {
now = now.add(Duration(days: DateTime(now.year, nextMonth, 0).day - now.day)); //
}
return now;
}
return Container(
decoration: BoxDecoration(
// color: Color.fromRGBO(244, 244, 244, 1),
// border: Border(bottom: BorderSide(color: Color.fromRGBO(204, 204, 204, 1), width: 1)),
),
child: Container(
alignment: Alignment.centerLeft,
decoration: BoxDecoration(border: Border(bottom: BorderSide(width: 1.r, color: Color(0xFFCCCCCC)))),
child: TabBar(
controller: controller,
unselectedLabelStyle: TextStyle(fontSize: 12.sp, color: const Color.fromRGBO(102, 102, 102, 1)),
labelStyle: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(116, 145, 253, 1),
),
isScrollable: true,
labelColor: Color(0xFF7491FD),
unselectedLabelColor: Color(0xFF505E6E),
padding: EdgeInsets.symmetric(horizontal: 14.r),
// indicatorSize: TabBarIndicatorSize.label, //
onTap: (int val) async {
switch (val) {
case 0: //
onTimeFilter(
CommonUtils.getWeekStartDate().toString().substring(0, 10),
CommonUtils.getWeekEndDate().toString().substring(0, 10),
);
break;
case 1: //
onTimeFilter(
getMonthStartDate().toString().substring(0, 10),
getMonthEndDate().toString().substring(0, 10),
);
break;
default: //
var dialogData = await showDialog<PickerDateRange?>(
context: context,
builder: (BuildContext context1) {
return Center(
child: Container(
color: Colors.white,
width: isPad() ? ScreenUtil().screenWidth / 2 : ScreenUtil().screenWidth / 1.3,
height: ScreenUtil().screenHeight / 2,
child: SfDateRangePicker(
showActionButtons: true,
confirmText: '确定',
cancelText: '取消',
onSubmit: (p0) {
print(p0);
Navigator.of(context1).pop(p0);
refreshTime(p0);
},
onCancel: () {
Navigator.of(context1).pop();
},
selectionMode: DateRangePickerSelectionMode.range,
initialSelectedRange: customTimeState,
),
),
);
});
// startDate: 2024-03-04 18:47:00.117958, endDate: 2024-03-11 18:47:00.117986
// if (dialogData != null && (dialogData.startDate != null || dialogData.endDate != null)) {}
onTimeFilter(
dialogData?.startDate?.toString().substring(0, 10),
dialogData?.endDate?.toString().substring(0, 10),
);
// customTimeState = dialogData!;
customTimeState = dialogData ?? PickerDateRange(null, null);
}
},
tabs: <Widget>[
const Tab(text: '近一周'),
const Tab(text: '近一月'),
Tab(text: customTimeStr),
],
),
),
);
}

View File

@ -2,6 +2,7 @@ import 'package:data_table_2/data_table_2.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
import 'package:marking_app/routes/RouterManager.dart';
class CardList extends StatefulWidget {
final List headList;
@ -11,6 +12,7 @@ class CardList extends StatefulWidget {
final int? fixedRows;
final int? fixedCols;
final bool? isHtml;
final bool? smallQuestion;
const CardList({
Key? key,
@ -19,6 +21,7 @@ class CardList extends StatefulWidget {
this.showCardDetail,
this.isScore = false,
this.isHtml = false,
this.smallQuestion = false,
this.fixedCols,
this.fixedRows,
}) : super(key: key);
@ -32,6 +35,7 @@ class _CardListState extends State<CardList> {
int? _sortColumnIndex;
bool _sortAscending = true;
DataRow _getRow(int index, [Color? color]) {
assert(index >= 0);
var body = widget.bodyList[index];
@ -40,16 +44,19 @@ class _CardListState extends State<CardList> {
color: color != null ? MaterialStateProperty.all(color) : null,
cells: List.generate(widget.headList.length, (itemIndex) {
var item = body[itemIndex];
// print(item);
return
itemIndex == 0 && widget.isScore == false ?DataCell(Center(
child: Text((index + 1).toString(),
style:
TextStyle(fontSize: 12.sp, color: Color(0xFF262626))),
)):
DataCell(itemIndex == 2 && widget.isScore == false
DataCell((itemIndex == 2 && widget.isScore == false)||(itemIndex == 1 && widget.smallQuestion == true)
? InkWell(
onTap: () {
if (widget.showCardDetail != null) {
if (widget.showCardDetail != null && itemIndex == 1 && item.toString().contains('{') && item['ExamNo'] != '') {
widget.showCardDetail!(context, index,studentNo:item['ExamNo']);
}else if (widget.showCardDetail != null && itemIndex == 2) {
widget.showCardDetail!(context, index);
}
},
@ -58,7 +65,7 @@ class _CardListState extends State<CardList> {
children: [
Expanded(
child: Center(
child: Text(item.toString(),
child: Text(item.toString().contains('{')?item['Name']:item.toString(),
style: TextStyle(
fontSize: 12.sp, color: Color(0xFF262626))),
),
@ -74,16 +81,24 @@ class _CardListState extends State<CardList> {
],
),
)
: Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child:
widget.isHtml == true?HtmlWidget(item.toString(),textStyle: TextStyle(fontSize: 12.sp,color: Color(0xFF262626)),):
Text(item.toString(),
style:
TextStyle(fontSize: 12.sp, color: Color(0xFF262626))),
: InkWell(
onTap: (){
if (widget.showCardDetail != null && item.toString().contains('{') && item['ExamNo'] != '') {
// print(item);
widget.showCardDetail!(context, index,studentNo:item['ExamNo']);
}
},
child: Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child:
widget.isHtml == true?HtmlWidget(item.toString().contains('{')?item['Name']: item.toString(),textStyle: TextStyle(fontSize: 12.sp,color: item.toString().contains('{') && item['ExamNo'] != ''?Color(0xFF6988FD):Color(0xFF262626)),):
Text(item.toString().contains('{')?item['Name']:item.toString(),
style:
TextStyle(fontSize: 12.sp, color: Color(0xFF262626))),
),
),
));
));
}),
);
}

View File

@ -0,0 +1,161 @@
import 'package:data_table_2/data_table_2.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
import 'package:marking_app/common/model/report/report_marking_detail.dart';
import 'package:photo_view/photo_view.dart';
class CompleteTable extends StatefulWidget {
final List bodyList;
final int? fixedRows;
final int? fixedCols;
const CompleteTable({
Key? key,
required this.bodyList,
this.fixedCols,
this.fixedRows,
}) : super(key: key);
@override
State<CompleteTable> createState() => _CompleteTableState();
}
class _CompleteTableState extends State<CompleteTable> {
final ScrollController _controller = ScrollController();
int? _sortColumnIndex;
bool _sortAscending = true;
final List<String> headList = ['题号','小题分','得分','用户答案','正确答案'];
showImg(String imgUrl) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
// insetPadding: EdgeInsets.symmetric(vertical: 10.r,horizontal: 45.r),
backgroundColor: Colors.transparent,
contentPadding: EdgeInsets.all(0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15.r))),
content: Container(
width: MediaQuery.of(context).size.width - 48.r,
height: MediaQuery.of(context).size.height * 0.6,
color: Colors.white,
child: PhotoView(imageProvider: NetworkImage(imgUrl),backgroundDecoration: BoxDecoration(color: Colors.transparent),)),
);
},
);
}
DataRow _getRow(int index, [Color? color]) {
assert(index >= 0);
QuestionAnswers body = widget.bodyList[index];
return DataRow2.byIndex(
index: index,
color: color != null ? MaterialStateProperty.all(color) : null,
cells: [
DataCell(
Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(body.questionNum,
style:
TextStyle(fontSize: 12.sp, color: Color(0xFF262626))),
),
)),
DataCell(
Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(body.totalScore.toString(),
style:
TextStyle(fontSize: 12.sp, color: Color(0xFF262626))),
),
)),
DataCell(
Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(body.score.toString(),
style:
TextStyle(fontSize: 12.sp, color: Color(0xFF262626))),
),
)),
DataCell(
Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child:
body.yourAnswer.contains('http')?
InkWell(
onTap: (){
showImg(body.yourAnswer);
},
child: Text('查看原题',style: TextStyle(fontSize: 12.sp,color: Color(0xFF6988FD)),),
):
Text(body.yourAnswer,
style:
TextStyle(fontSize: 12.sp, color: Color(0xFF262626)))
,
),
)),
DataCell(
Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.r),
child: Text(body.answer,
style:
TextStyle(fontSize: 12.sp, color: Color(0xFF262626))),
),
)),
],
);
}
@override
Widget build(BuildContext context) {
return DataTable2(
dividerThickness: 0,
scrollController: _controller,
columnSpacing: 0,
horizontalMargin: 0,
dataRowHeight:40.r,
headingRowHeight: 30.r,
bottomMargin: 0,
border: TableBorder(
left: BorderSide(
width: 1, color: Color(0xFFEAEAEA), style: BorderStyle.solid),
right: BorderSide(
width: 1, color: Color(0xFFEAEAEA), style: BorderStyle.solid),
horizontalInside: BorderSide(
width: 1, color: Color(0xFFEAEAEA), style: BorderStyle.solid),
bottom: BorderSide(
width: 1, color: Color(0xFFEAEAEA), style: BorderStyle.solid),
verticalInside: BorderSide(
width: 1, color: Color(0xFFEAEAEA), style: BorderStyle.solid)),
headingRowColor: MaterialStateProperty.resolveWith((states) =>
widget.fixedCols! > 0 ? Color(0xFFF0F3FF) : Colors.transparent),
headingRowDecoration: BoxDecoration(color: Color(0xFFF0F3FF)),
fixedColumnsColor: Color(0xFFF0F3FF),
fixedCornerColor: Colors.grey[400],
minWidth:MediaQuery.of(context).size.width,
fixedTopRows: widget.fixedRows!,
fixedLeftColumns: widget.fixedCols!,
sortColumnIndex: _sortColumnIndex,
sortAscending: _sortAscending,
// onSelectAll: (val) => setState(() => selectAll(val)),
columns: List.generate(headList.length, (index) {
var item = headList[index];
return DataColumn2(
label: Center(
child: Text(item,
style: TextStyle(fontSize: 12.sp, color: Color(0xFF505767))),
),
// size: ColumnSize.S,
fixedWidth:(MediaQuery.of(context).size.width - 48.r)/headList.length,
);
}),
rows: List<DataRow>.generate(widget.bodyList.length,
(index) => _getRow(index, Colors.transparent)));
}
}

View File

@ -10,6 +10,7 @@ import 'package:marking_app/common/model/report/report_card.dart';
import 'package:marking_app/common/model/report/report_marking_detail.dart';
import 'package:marking_app/common/model/report/report_marking_detail_params.dart';
import 'package:marking_app/pages/report_detail/widgets/custom_rect.dart';
import 'package:marking_app/routes/RouterManager.dart';
import 'package:marking_app/utils/easy_refresh/MyEmptyWidget.dart';
import 'package:marking_app/utils/request/rest_client_report.dart';
@ -32,6 +33,7 @@ class _ReportCardDialogState extends ConsumerState<ReportCardDialog>
int currentSubjectId = 0;
final viewTransformationController = TransformationController();
bool isList = false;
void initState() {
final zoomFactor = 0.5;
@ -68,7 +70,6 @@ class _ReportCardDialogState extends ConsumerState<ReportCardDialog>
if(res.data!=null){
examOrigin = res.data!.examOriginPapers[0];
examOriginList = res.data!.examOriginPapers;
// print('examOrigin!.width=${examOrigin!.width}');
}else{
examOriginList = [];
examOrigin = null;
@ -83,28 +84,66 @@ class _ReportCardDialogState extends ConsumerState<ReportCardDialog>
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Column(children: [
Padding(
padding: EdgeInsets.only(top: 10.r, left: 20.r, right: 20.r),
color: Color(0xFFEDEFFF),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
widget.cardItem.name,
style: TextStyle(
fontSize: 14.sp,
color: Color(0xFF6787FD),
fontWeight: FontWeight.w500),
),
InkWell(
onTap: (){
Navigator.pop(context);
},
child: Icon(Icons.close,color: Colors.grey,size: 20.r,))
],
),
Text(
'张沫凡重庆八中2023.2024 高二定时训练',
style: TextStyle(
fontSize: 14.sp,
color: Color(0xFF6787FD),
fontWeight: FontWeight.w500),
),
InkWell(
onTap: (){
RouterManager.router.navigateTo(context, RouterManager.reportHistoryPath);
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 3.r,horizontal: 5.r),
decoration: BoxDecoration(
border: Border.all(width: 1.r,color: Color(0xFF6988FD)),
borderRadius: BorderRadius.circular(5.r),
),
child: Center(
child: Text('历次成绩',style: TextStyle(fontSize: 10.r,color: Color(0xFF6988FD)),),
),
),
),
Container(
margin: EdgeInsets.only(top: 10.r, left: 14.r, right: 14.r),
padding: EdgeInsets.symmetric(horizontal: 10.r),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
color: Colors.white,
boxShadow: [
BoxShadow(
color: const Color.fromRGBO(0, 0, 0, 0.1),
offset: Offset(0, 0), //y轴偏移量
blurRadius: 2, //
spreadRadius: 1, //
)
],
),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
widget.cardItem.name,
style: TextStyle(
fontSize: 14.sp,
color: Color(0xFF6787FD),
fontWeight: FontWeight.w500),
),
InkWell(
onTap: (){
Navigator.pop(context);
},
child: Icon(Icons.close,color: Colors.grey,size: 20.r,))
],
),
Container(
margin: EdgeInsets.only(top: 10.r),
width: double.infinity,
@ -119,7 +158,7 @@ class _ReportCardDialogState extends ConsumerState<ReportCardDialog>
(index) {
var item = widget.headList[index];
return Container(
width: (MediaQuery.of(context).size.width - 90.r) / 7,
width: (MediaQuery.of(context).size.width - 104.r) / 7,
child: _subjectText(item));
}),
),
@ -133,20 +172,20 @@ class _ReportCardDialogState extends ConsumerState<ReportCardDialog>
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
width: (MediaQuery.of(context).size.width - 90.r) / 7,
width: (MediaQuery.of(context).size.width - 104.r) / 7,
child: _subjectText(
widget.cardItem.totalScore.toString())),
Container(
width: (MediaQuery.of(context).size.width - 90.r) / 7,
width: (MediaQuery.of(context).size.width - 104.r) / 7,
child: _subjectText(
widget.cardItem.totalClassRanking.toString())),
Container(
width: (MediaQuery.of(context).size.width - 90.r) / 7,
width: (MediaQuery.of(context).size.width - 104.r) / 7,
child: _subjectText(
widget.cardItem.totalRanking.toString())),
SizedBox(
width:
(MediaQuery.of(context).size.width - 90.r) / 7 * 4,
(MediaQuery.of(context).size.width - 104.r) / 7 * 4,
child: Row(
children: List.generate(
widget.cardItem.subjectDetails.length > 4
@ -156,7 +195,7 @@ class _ReportCardDialogState extends ConsumerState<ReportCardDialog>
var subject = widget.cardItem.subjectDetails[index];
return Container(
width:
(MediaQuery.of(context).size.width - 90.r) /
(MediaQuery.of(context).size.width - 104.r) /
7,
child: _subjectText(subject.score));
}),
@ -177,7 +216,7 @@ class _ReportCardDialogState extends ConsumerState<ReportCardDialog>
List.generate(widget.headList.length - 7, (index) {
var item = widget.headList[index + 7];
return Container(
width: (MediaQuery.of(context).size.width - 90.r) / 7,
width: (MediaQuery.of(context).size.width - 104.r) / 7,
child: _subjectText(item));
}),
),
@ -194,7 +233,7 @@ class _ReportCardDialogState extends ConsumerState<ReportCardDialog>
widget.cardItem.subjectDetails.length - 4, (index) {
var subject = widget.cardItem.subjectDetails[index + 4];
return Container(
width: (MediaQuery.of(context).size.width - 90.r) / 7,
width: (MediaQuery.of(context).size.width - 104.r) / 7,
child: _subjectText(subject.score));
}),
),
@ -202,161 +241,276 @@ class _ReportCardDialogState extends ConsumerState<ReportCardDialog>
],
),
),
SizedBox(height: 10.r,),
Expanded(
child: Container(
margin: EdgeInsets.only(top: 0.r),
padding: EdgeInsets.symmetric(vertical: 5.r, horizontal: 20.r),
child: Stack(
children: [
Container(
margin: EdgeInsets.only(top: 10.r, left: 14.r, right: 14.r),
padding: EdgeInsets.symmetric(vertical:15.r,horizontal: 10.r),
/* margin: EdgeInsets.only(top: 0.r),
padding: EdgeInsets.symmetric(vertical: 5.r, horizontal: 20.r),*/
width: double.infinity,
decoration: BoxDecoration(
color: Color(0xFFEFF1FF),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(15.r),
bottomRight: Radius.circular(15.r))),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
color: Colors.white,
boxShadow: [
BoxShadow(
color: const Color.fromRGBO(0, 0, 0, 0.1),
offset: Offset(0, 0), //y轴偏移量
blurRadius: 2, //
spreadRadius: 1, //
)
],
),
child: Column(
children: [
SizedBox(
height: 30.r,
width: MediaQuery.of(context).size.width,
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
var item = subjectList[index];
return InkWell(
onTap: () {
setState(() {
subjectList.forEach((element) {
element.isCheck = false;
});
item.isCheck = true;
currentSubjectId = item.value;
EasyLoading.show(status: 'loading...');
getImageDetail();
});
},
child: Container(
width: 30.r,
height: 30.r,
margin: EdgeInsets.only(
right: index == subjectList.length
? 0
: (MediaQuery.of(context).size.width -
30.r * 9 -
110.r) /
8),
decoration: BoxDecoration(
color: item.isCheck
? Color(0xFF6787FD)
: Color(0xFFFFFFFF),
shape: BoxShape.circle,
// borderRadius: BorderRadius.all(Radius.circular(13.r)),
),
child: Center(
child: Text(
item.text,
style: TextStyle(
fontSize: 11.sp,
color: item.isCheck
? Colors.white
: Color(0xFF667095),
fontWeight: FontWeight.w400),
)),
),
);
},
itemCount: subjectList.length,
scrollDirection: Axis.horizontal,
),
),
Expanded(
child: examOrigin != null && examOrigin!.imageUrl != ''
? Padding(
padding: EdgeInsets.only(top:5.r),
child: InteractiveViewer(
transformationController: viewTransformationController,
constrained: false,
boundaryMargin: EdgeInsets.all(140.r),
minScale: 0.1, //
maxScale: 4.0, //
child: CustomRect(examOrigin!)),
)
: MyEmptyWidget(),
),
SizedBox(height: 6.r,),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
InkWell(
onTap: () {
var num = examOrigin!.pageIndex;
if (num > 1) {
setState(() {
examOrigin = examOriginList[num - 1 - 1];
});
}
},
child:Container(
padding: EdgeInsets.symmetric(
vertical: 2.r, horizontal: 5.r),
decoration: BoxDecoration(
border: Border.all(
color: examOrigin != null && examOrigin!.pageIndex > 1?Color(0xFF6787FD): Color(0xFFB3B9B9),
width: 1.r),
borderRadius: BorderRadius.all(
Radius.circular(2.r)),
),
child: Text(
'上一页',
style: TextStyle(
color: examOrigin != null && examOrigin!.pageIndex > 1?Color(0xFF6787FD): Color(0xFFB3B9B9),
),
),
),
/* Image.asset(
'assets/images/report_left_icon.png',
width: 33.r,
height: 33.r,
)*/
),
SizedBox(
width: 15.r,
),
InkWell(
onTap: () {
var num = examOrigin!.pageIndex;
if (num < examOriginList.length) {
setState(() {
examOrigin = examOriginList[num];
});
}
height: 30.r,
width: MediaQuery.of(context).size.width,
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
var item = subjectList[index];
return InkWell(
onTap: () {
setState(() {
subjectList.forEach((element) {
element.isCheck = false;
});
item.isCheck = true;
currentSubjectId = item.value;
EasyLoading.show(status: 'loading...');
getImageDetail();
});
},
child: Container(
width: 30.r,
height: 30.r,
margin: EdgeInsets.only(
right: index == subjectList.length
? 0
: (MediaQuery.of(context).size.width -
30.r * 9 -
104.r) /
8),
decoration: BoxDecoration(
color: item.isCheck
? Color(0xFF6787FD)
: Color(0xFFFFFFFF),
shape: BoxShape.circle,
// borderRadius: BorderRadius.all(Radius.circular(13.r)),
),
child: Center(
child: Text(
item.text,
style: TextStyle(
fontSize: 11.sp,
color: item.isCheck
? Colors.white
: Color(0xFF667095),
fontWeight: FontWeight.w400),
)),
),
);
},
child: Container(
padding: EdgeInsets.symmetric(
vertical: 2.r, horizontal: 5.r),
decoration: BoxDecoration(
border: Border.all(
color: examOrigin != null && examOrigin!.pageIndex < examOriginList.length?Color(0xFF6787FD): Color(0xFFB3B9B9),
width: 1.r),
borderRadius: BorderRadius.all(
Radius.circular(2.r)),
),
child: Text(
'下一页',
style: TextStyle(
color: examOrigin != null && examOrigin!.pageIndex < examOriginList.length?Color(0xFF6787FD): Color(0xFFB3B9B9),
itemCount: subjectList.length,
scrollDirection: Axis.horizontal,
),
),
Expanded(
child: examOrigin != null && examOrigin!.imageUrl != ''
? !isList?Padding(
padding: EdgeInsets.only(top:5.r),
child: InteractiveViewer(
transformationController: viewTransformationController,
constrained: false,
boundaryMargin: EdgeInsets.all(140.r),
minScale: 0.1, //
maxScale: 4.0, //
child: CustomRect(examOrigin!)),
):Text('list')
: MyEmptyWidget(),
),
SizedBox(height: 6.r,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
flex: 1,
child: InkWell(
onTap:(){
isList = false;
setState(() {
});
},
child: Container(
height: 27.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
color: !isList?Color(0xFF6988FD):Color(0xFFEDEFFF),
),
child: Center(
child: Text('查看原卷',style: TextStyle(fontSize: 12.sp,color: !isList?Colors.white:Color(0xFF7B7B7E)),),
),
),
),
),
/* Image.asset(
'assets/images/report_right_icon.png',
width: 33.r,
height: 33.r,
)*/
SizedBox(width: 20.r,),
Flexible(
flex: 1,
child: InkWell(
onTap: (){
isList = true;
setState(() {
});
},
child: Container(
height: 27.r,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
color: isList?Color(0xFF6988FD):Color(0xFFEDEFFF),
),
child: Center(
child: Text('查看列题',style: TextStyle(fontSize: 12.sp,color: isList?Colors.white:Color(0xFF7B7B7E)),),
),
),
),
),
],
),
/*if(!isList)
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
InkWell(
onTap: () {
var num = examOrigin!.pageIndex;
if (num > 1) {
setState(() {
examOrigin = examOriginList[num - 1 - 1];
});
}
},
child:Column(
children: [
Opacity(
opacity: examOrigin != null && examOrigin!.pageIndex > 1?1:0.3,
child: Image.asset('assets/images/report_left_icon.png',width: 33.r,height: 33.r,)),
Container(
padding: EdgeInsets.symmetric( horizontal: 5.r),
decoration: BoxDecoration(
*//* border: Border.all(
color: examOrigin != null && examOrigin!.pageIndex > 1?Color(0xFF6787FD): Color(0xFFB3B9B9),
width: 1.r),*//*
borderRadius: BorderRadius.all(
Radius.circular(2.r)),
),
child: Text(
'上一页',
style: TextStyle(
color: examOrigin != null && examOrigin!.pageIndex > 1?Color(0xFF6787FD): Color(0xFFB3B9B9),
),
),
),
],
),
*//* Image.asset(
'assets/images/report_left_icon.png',
width: 33.r,
height: 33.r,
)*//*
),
SizedBox(
width: 15.r,
),
InkWell(
onTap: () {
var num = examOrigin!.pageIndex;
if (num < examOriginList.length) {
setState(() {
examOrigin = examOriginList[num];
});
}
},
child: Column(
children: [
Opacity(
opacity:examOrigin != null && examOrigin!.pageIndex < examOriginList.length?1:0.3,
child: Image.asset('assets/images/report_right_icon.png',width: 33.r,height: 33.r,)),
Container(
padding: EdgeInsets.symmetric(horizontal: 5.r),
decoration: BoxDecoration(
*//* border: Border.all(
color: examOrigin != null && examOrigin!.pageIndex < examOriginList.length?Color(0xFF6787FD): Color(0xFFB3B9B9),
width: 1.r),*//*
borderRadius: BorderRadius.all(
Radius.circular(2.r)),
),
child: Text(
'下一页',
style: TextStyle(
color: examOrigin != null && examOrigin!.pageIndex < examOriginList.length?Color(0xFF6787FD): Color(0xFFB3B9B9),
),
),
),
],
),
*//* Image.asset(
'assets/images/report_right_icon.png',
width: 33.r,
height: 33.r,
)*//*
),
],
),*/
],
),
],
),
))
),
if(!isList)
Positioned(
left:0.r,
top: MediaQuery.of(context).size.height/4,
child: InkWell(
onTap: () {
var num = examOrigin!.pageIndex;
if (num > 1) {
setState(() {
examOrigin = examOriginList[num - 1 - 1];
});
}
},
child:Opacity(
opacity: examOrigin != null && examOrigin!.pageIndex > 1?1:0.3,
child: Image.asset('assets/images/report_left_icon.png',width: 33.r,height: 33.r,)),
),),
if(!isList)
Positioned(
right: 0,
top: MediaQuery.of(context).size.height/4,
child: InkWell(
onTap: () {
var num = examOrigin!.pageIndex;
if (num < examOriginList.length) {
setState(() {
examOrigin = examOriginList[num];
});
}
},
child: Opacity(
opacity:examOrigin != null && examOrigin!.pageIndex < examOriginList.length?1:0.3,
child: Image.asset('assets/images/report_right_icon.png',width: 33.r,height: 33.r,)),
/* Image.asset(
'assets/images/report_right_icon.png',
width: 33.r,
height: 33.r,
)*/
),)
],
))
]),
);
}

View File

@ -181,6 +181,7 @@ class _TheReportState extends ConsumerState<TheReport>
RestClientReport clientReport = await getClientReport();
UserInfoReport _userReport = ref.read(userReportProvider);
if (!_userReport.normal) {
if(ref.read(userProvider).id == '540117143121989') return null;
// 使
bool theFlag =
await ref.read(userReportProvider.notifier).initUserReport();

Some files were not shown because too many files have changed in this diff Show More