Compare commits
1 Commits
master
...
the_window
| Author | SHA1 | Date |
|---|---|---|
|
|
a0131636a5 |
|
|
@ -1,3 +1,4 @@
|
||||||
{
|
{
|
||||||
"dart.flutterSdkPath": ".fvm/versions/3.32.0"
|
"dart.flutterSdkPath": ".fvm/versions/3.32.0",
|
||||||
|
"java.configuration.updateBuildConfiguration": "interactive"
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
|
class PlatformUtils {
|
||||||
|
static bool get isDesktop =>
|
||||||
|
defaultTargetPlatform == TargetPlatform.windows ||
|
||||||
|
defaultTargetPlatform == TargetPlatform.linux ||
|
||||||
|
defaultTargetPlatform == TargetPlatform.macOS;
|
||||||
|
|
||||||
|
static bool get isMobile =>
|
||||||
|
defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS;
|
||||||
|
}
|
||||||
|
|
@ -11,6 +11,7 @@ import 'package:get/get.dart';
|
||||||
import 'package:making_school_asignment_app/common/config/app_config.dart';
|
import 'package:making_school_asignment_app/common/config/app_config.dart';
|
||||||
import 'package:making_school_asignment_app/common/config/colorUtils.dart';
|
import 'package:making_school_asignment_app/common/config/colorUtils.dart';
|
||||||
import 'package:making_school_asignment_app/common/store/user_store.dart';
|
import 'package:making_school_asignment_app/common/store/user_store.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/utils/platform_utils.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/storage.dart';
|
import 'package:making_school_asignment_app/common/utils/storage.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/utils.dart';
|
import 'package:making_school_asignment_app/common/utils/utils.dart';
|
||||||
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
|
@ -41,8 +42,11 @@ void main() async {
|
||||||
statusBarColor: Colors.transparent, //状态栏背景颜色
|
statusBarColor: Colors.transparent, //状态栏背景颜色
|
||||||
statusBarIconBrightness: Brightness.light // dark:一般显示黑色 light:一般显示白色
|
statusBarIconBrightness: Brightness.light // dark:一般显示黑色 light:一般显示白色
|
||||||
));
|
));
|
||||||
|
if (PlatformUtils.isMobile) {
|
||||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky, overlays: [SystemUiOverlay.top]); // 屏幕刘海
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky, overlays: [SystemUiOverlay.top]); // 屏幕刘海
|
||||||
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); // 屏幕强制竖屏
|
await SystemChrome.setPreferredOrientations(
|
||||||
|
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); // 屏幕强制竖屏
|
||||||
|
}
|
||||||
runApp(const MyApp());
|
runApp(const MyApp());
|
||||||
|
|
||||||
Future.delayed(const Duration(seconds: 3), () => FlutterNativeSplash.remove());
|
Future.delayed(const Duration(seconds: 3), () => FlutterNativeSplash.remove());
|
||||||
|
|
@ -57,7 +61,8 @@ class MyApp extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// String? oldRouter;
|
// String? oldRouter;
|
||||||
return ScreenUtilInit(
|
return ScreenUtilInit(
|
||||||
designSize: const Size(AppConfig.UI_WIDTH, AppConfig.UI_HEIGHT),
|
designSize:
|
||||||
|
PlatformUtils.isDesktop ? const Size(1920, 1080) : const Size(AppConfig.UI_WIDTH, AppConfig.UI_HEIGHT),
|
||||||
/* minTextAdapt: true,
|
/* minTextAdapt: true,
|
||||||
splitScreenMode: true,*/
|
splitScreenMode: true,*/
|
||||||
builder: () => GetMaterialApp(
|
builder: () => GetMaterialApp(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
|
||||||
|
class DesktopPageTemplate extends StatelessWidget {
|
||||||
|
final String title;
|
||||||
|
final Widget? child;
|
||||||
|
final List<Widget>? actions;
|
||||||
|
final String? subtitle;
|
||||||
|
|
||||||
|
const DesktopPageTemplate({
|
||||||
|
super.key,
|
||||||
|
required this.title,
|
||||||
|
this.child,
|
||||||
|
this.actions,
|
||||||
|
this.subtitle,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: const Color(0xFFF0F2F5),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
_buildHeader(context),
|
||||||
|
Expanded(
|
||||||
|
child: child ?? _buildPlaceholder(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildHeader(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.all(24.r),
|
||||||
|
color: Colors.white,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 24.sp,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: const Color(0xFF333333),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (subtitle != null) ...[
|
||||||
|
SizedBox(height: 4.h),
|
||||||
|
Text(
|
||||||
|
subtitle!,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
color: Colors.grey[600],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (actions != null)
|
||||||
|
Row(children: actions!)
|
||||||
|
else
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
icon: Icon(Icons.close, size: 24.sp, color: Colors.grey[600]),
|
||||||
|
tooltip: '关闭',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildPlaceholder() {
|
||||||
|
return Center(
|
||||||
|
child: Card(
|
||||||
|
elevation: 2,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.r)),
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(48.r),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.desktop_windows_outlined,
|
||||||
|
size: 64.r,
|
||||||
|
color: Colors.grey[400],
|
||||||
|
),
|
||||||
|
SizedBox(height: 16.h),
|
||||||
|
Text(
|
||||||
|
'桌面版 $title',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 20.sp,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: const Color(0xFF333333),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 8.h),
|
||||||
|
Text(
|
||||||
|
'此页面已针对 Windows 桌面环境进行优化',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
color: Colors.grey[600],
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
SizedBox(height: 24.h),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {},
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 12.h),
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.r)),
|
||||||
|
),
|
||||||
|
child: const Text('返回'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/home_page/children/my_info.dart';
|
||||||
|
|
||||||
|
import '../home_page/home_view.dart';
|
||||||
|
|
||||||
|
class DesktopScaffold extends StatefulWidget {
|
||||||
|
const DesktopScaffold({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<DesktopScaffold> createState() => _DesktopScaffoldState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DesktopScaffoldState extends State<DesktopScaffold> {
|
||||||
|
int _selectedIndex = 0;
|
||||||
|
final List<Widget> _pages = [const HomePage(), const MyInfo()];
|
||||||
|
bool _isExpanded = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: const Color(0xFFF0F2F5),
|
||||||
|
body: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.05),
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(2, 0),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: NavigationRail(
|
||||||
|
selectedIndex: _selectedIndex,
|
||||||
|
onDestinationSelected: (int index) {
|
||||||
|
setState(() {
|
||||||
|
_selectedIndex = index;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
extended: _isExpanded,
|
||||||
|
minWidth: 72.w,
|
||||||
|
minExtendedWidth: 200.w,
|
||||||
|
labelType: _isExpanded ? NavigationRailLabelType.none : NavigationRailLabelType.selected,
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
selectedIconTheme: IconThemeData(
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
size: 28.r,
|
||||||
|
),
|
||||||
|
unselectedIconTheme: IconThemeData(
|
||||||
|
color: Colors.grey[600],
|
||||||
|
size: 24.r,
|
||||||
|
),
|
||||||
|
selectedLabelTextStyle: TextStyle(
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 12.sp,
|
||||||
|
),
|
||||||
|
unselectedLabelTextStyle: TextStyle(
|
||||||
|
color: Colors.grey[600],
|
||||||
|
fontSize: 12.sp,
|
||||||
|
),
|
||||||
|
leading: Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 16.h),
|
||||||
|
child: FloatingActionButton.small(
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_isExpanded = !_isExpanded;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
backgroundColor: Colors.grey[100],
|
||||||
|
foregroundColor: Colors.grey[700],
|
||||||
|
elevation: 0,
|
||||||
|
child: Icon(_isExpanded ? Icons.chevron_left : Icons.menu, size: 20.r),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
destinations: const <NavigationRailDestination>[
|
||||||
|
NavigationRailDestination(
|
||||||
|
icon: Icon(Icons.assignment_outlined),
|
||||||
|
selectedIcon: Icon(Icons.assignment),
|
||||||
|
label: Text('作业管理'),
|
||||||
|
),
|
||||||
|
NavigationRailDestination(
|
||||||
|
icon: Icon(Icons.person_outline),
|
||||||
|
selectedIcon: Icon(Icons.person),
|
||||||
|
label: Text('个人信息'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: _pages[_selectedIndex],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,159 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/const_text.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/job/user_info_detail.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/store/user_store.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/utils/storage.dart';
|
||||||
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
|
||||||
|
class OtherDesktopPage extends StatefulWidget {
|
||||||
|
const OtherDesktopPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<OtherDesktopPage> createState() => _OtherDesktopPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _OtherDesktopPageState extends State<OtherDesktopPage> with RequestToolMixin {
|
||||||
|
late Rx<UserInfoDetail?> userInfo = UserStore.to.userDetailInfo;
|
||||||
|
RxString localVersion = ''.obs;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
getPageInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
getPageInfo() async {
|
||||||
|
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||||
|
localVersion.value = packageInfo.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
_showLogoutDialog(BuildContext context) async {
|
||||||
|
return showDialog<bool>(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('账户注销'),
|
||||||
|
content: const Text('账户注销无法恢复,您确定要注销账户吗?'),
|
||||||
|
actions: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
child: const Text('取消'),
|
||||||
|
onPressed: () => Navigator.of(context).pop(false),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
child: const Text('确定'),
|
||||||
|
onPressed: () async {
|
||||||
|
await getClient().toUserLogout(userInfo.value!.id);
|
||||||
|
try {
|
||||||
|
UserStore.to.erase();
|
||||||
|
await StorageService.to.erase();
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
Get.offAllNamed(Routes.login);
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: const Color(0xFFF0F2F5),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
padding: EdgeInsets.all(24.r),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_buildHeader(),
|
||||||
|
SizedBox(height: 24.h),
|
||||||
|
_buildSettingsCards(),
|
||||||
|
SizedBox(height: 24.h),
|
||||||
|
_buildVersionInfo(),
|
||||||
|
SizedBox(height: 24.h),
|
||||||
|
_buildLogoutSection(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildHeader() {
|
||||||
|
return Text(
|
||||||
|
'其他设置',
|
||||||
|
style: TextStyle(fontSize: 24.sp, fontWeight: FontWeight.bold, color: const Color(0xFF333333)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildSettingsCards() {
|
||||||
|
return Card(
|
||||||
|
elevation: 2,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.r)),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Icons.privacy_tip_outlined, color: Colors.grey[600]),
|
||||||
|
title: const Text('用户隐私协议'),
|
||||||
|
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.agreementPage, arguments: {"type": AGREEMENT_KEY.PRIVACY_GREEMENT.name});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const Divider(height: 1),
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Icons.description_outlined, color: Colors.grey[600]),
|
||||||
|
title: const Text('用户协议'),
|
||||||
|
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.agreementPage, arguments: {"type": AGREEMENT_KEY.USER_AGREEMENT.name});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildVersionInfo() {
|
||||||
|
return Card(
|
||||||
|
elevation: 2,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.r)),
|
||||||
|
child: ListTile(
|
||||||
|
leading: Icon(Icons.info_outline, color: Colors.grey[600]),
|
||||||
|
title: const Text('APP版本'),
|
||||||
|
trailing: Obx(() => Text(localVersion.value, style: TextStyle(color: Colors.grey[600]))),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildLogoutSection() {
|
||||||
|
return Card(
|
||||||
|
elevation: 2,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.r)),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Icons.logout, color: Colors.red[600]),
|
||||||
|
title: Text('账户注销', style: TextStyle(color: Colors.red[600])),
|
||||||
|
trailing: Icon(Icons.arrow_forward_ios, size: 16, color: Colors.red[600]),
|
||||||
|
onTap: () => _showLogoutDialog(context),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.all(16.r),
|
||||||
|
child: Text(
|
||||||
|
'APP备案号: 渝ICP备17007225号-4A',
|
||||||
|
style: TextStyle(fontSize: 12.sp, color: Colors.grey[500]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,189 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/const_text.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/job/user_info_detail.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/store/user_store.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/utils/storage.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
||||||
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
|
||||||
|
class OtherMobilePage extends StatefulWidget {
|
||||||
|
const OtherMobilePage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<OtherMobilePage> createState() => _OtherMobilePageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _OtherMobilePageState extends State<OtherMobilePage> with RequestToolMixin {
|
||||||
|
late Rx<UserInfoDetail?> userInfo = UserStore.to.userDetailInfo;
|
||||||
|
RxString localVersion = ''.obs;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
getPageInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前版本号
|
||||||
|
getPageInfo() async {
|
||||||
|
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||||
|
localVersion.value = packageInfo.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认对话框
|
||||||
|
_showAlertDialog(context1) async {
|
||||||
|
await showDialog(
|
||||||
|
barrierDismissible: false,
|
||||||
|
context: context1,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(title: quickText("提示信息"), content: quickText("账户注销无法恢复,您确定要注销账户吗?"), actions: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
child: quickText("取消"),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context, 'Cancle');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
child: quickText("确定"),
|
||||||
|
onPressed: () async {
|
||||||
|
await getClient().toUserLogout(userInfo.value!.id);
|
||||||
|
try {
|
||||||
|
UserStore.to.erase();
|
||||||
|
var msg = await StorageService.to.erase();
|
||||||
|
print(msg);
|
||||||
|
Navigator.pop(context, "Ok");
|
||||||
|
Get.offAllNamed(Routes.login);
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final personalInfoTitleStly = TextStyle(
|
||||||
|
color: const Color.fromRGBO(80, 87, 103, 1),
|
||||||
|
fontSize: 16.sp,
|
||||||
|
);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: const Color.fromRGBO(248, 248, 248, 1),
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Theme.of(context).primaryColor,
|
||||||
|
title: quickText('其他', color: Colors.white),
|
||||||
|
),
|
||||||
|
body: Stack(
|
||||||
|
alignment: const FractionalOffset(0.5, 0.98),
|
||||||
|
children: [
|
||||||
|
ListView(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
margin: EdgeInsets.symmetric(vertical: 22.h, horizontal: 16.w),
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 22.h, horizontal: 16.w),
|
||||||
|
height: 130.h,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(6.w)),
|
||||||
|
color: Colors.white,
|
||||||
|
boxShadow: const [
|
||||||
|
BoxShadow(
|
||||||
|
color: Color.fromRGBO(46, 91, 255, 0.1),
|
||||||
|
offset: Offset.zero,
|
||||||
|
blurRadius: 20,
|
||||||
|
spreadRadius: 10,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.agreementPage, arguments: {"type": AGREEMENT_KEY.PRIVACY_GREEMENT.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),
|
||||||
|
Obx(() {
|
||||||
|
return quickText(localVersion);
|
||||||
|
})
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
bottom: 50.h,
|
||||||
|
child: InkWell(
|
||||||
|
child: Container(
|
||||||
|
height: 46.h,
|
||||||
|
width: ScreenUtil().screenWidth - 60.w,
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 14.h),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(6.w)),
|
||||||
|
color: Colors.white,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: const Color.fromRGBO(46, 91, 255, 0.2),
|
||||||
|
offset: Offset(2.w, 2.h),
|
||||||
|
blurRadius: 14,
|
||||||
|
spreadRadius: 0.5,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.exit_to_app_outlined,
|
||||||
|
size: 13.sp,
|
||||||
|
color: const Color.fromRGBO(148, 163, 182, 1),
|
||||||
|
),
|
||||||
|
Container(width: 6.w),
|
||||||
|
Text(
|
||||||
|
'账户注销',
|
||||||
|
style: TextStyle(color: const Color.fromRGBO(148, 163, 182, 1), fontSize: 13.sp),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTap: () => _showAlertDialog(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [Text('APP备案号: ', style: personalInfoTitleStly), quickText('渝ICP备17007225号-4A', size: 14.sp)],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,199 +1,13 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:making_school_asignment_app/common/utils/platform_utils.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:making_school_asignment_app/page/global_widget/other_desktop_page.dart';
|
||||||
import 'package:making_school_asignment_app/common/const_text.dart';
|
import 'package:making_school_asignment_app/page/global_widget/other_mobile_page.dart';
|
||||||
import 'package:making_school_asignment_app/common/job/user_info_detail.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/store/user_store.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/utils/storage.dart';
|
|
||||||
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
|
||||||
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
|
||||||
// 其他页面
|
|
||||||
|
|
||||||
class OhterPage extends StatefulWidget {
|
class OhterPage extends StatelessWidget {
|
||||||
const OhterPage({super.key});
|
const OhterPage({super.key});
|
||||||
|
|
||||||
@override
|
|
||||||
State<OhterPage> createState() => _OhterPageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _OhterPageState extends State<OhterPage> with RequestToolMixin {
|
|
||||||
late Rx<UserInfoDetail?> userInfo = UserStore.to.userDetailInfo;
|
|
||||||
RxString localVersion = ''.obs;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
getPageInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取当前版本号
|
|
||||||
getPageInfo() async {
|
|
||||||
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
|
||||||
localVersion.value = packageInfo.version;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确认对话框
|
|
||||||
_showAlertDialog(context1) async {
|
|
||||||
await showDialog(
|
|
||||||
// 表示点击灰色背景的时候是否消失弹出框
|
|
||||||
barrierDismissible: false,
|
|
||||||
context: context1,
|
|
||||||
builder: (context) {
|
|
||||||
return AlertDialog(title: quickText("提示信息"), content: quickText("账户注销无法恢复,您确定要注销账户吗?"), actions: <Widget>[
|
|
||||||
TextButton(
|
|
||||||
child: quickText("取消"),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.pop(context, 'Cancle');
|
|
||||||
},
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
child: quickText("确定"),
|
|
||||||
onPressed: () async {
|
|
||||||
/* ref.read(markingKeyboardProvider.notifier).clean();
|
|
||||||
ref.read(markingSubtopicSwitchingProvider.notifier).clean();
|
|
||||||
ref.read(userTokenProvider.notifier).clean();
|
|
||||||
ref.read(userProvider.notifier).clean();*/
|
|
||||||
await getClient().toUserLogout(userInfo.value!.id);
|
|
||||||
try {
|
|
||||||
UserStore.to.erase();
|
|
||||||
var msg = await StorageService.to.erase();
|
|
||||||
print(msg);
|
|
||||||
Navigator.pop(context, "Ok");
|
|
||||||
Get.offAllNamed(Routes.login);
|
|
||||||
} catch (e) {
|
|
||||||
print(e);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final personalInfoTitleStly = TextStyle(
|
return PlatformUtils.isDesktop ? const OtherDesktopPage() : const OtherMobilePage();
|
||||||
color: const Color.fromRGBO(80, 87, 103, 1),
|
|
||||||
fontSize: 16.sp,
|
|
||||||
);
|
|
||||||
|
|
||||||
return Scaffold(
|
|
||||||
backgroundColor: const Color.fromRGBO(248, 248, 248, 1),
|
|
||||||
appBar: AppBar(
|
|
||||||
backgroundColor: Theme.of(context).primaryColor,
|
|
||||||
title: quickText('其他', color: Colors.white),
|
|
||||||
),
|
|
||||||
body: Stack(
|
|
||||||
alignment: const FractionalOffset(0.5, 0.98),
|
|
||||||
children: [
|
|
||||||
ListView(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
margin: EdgeInsets.symmetric(vertical: 22.h, horizontal: 16.w),
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 22.h, horizontal: 16.w),
|
|
||||||
height: 130.h,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(6.w)),
|
|
||||||
color: Colors.white,
|
|
||||||
boxShadow: const [
|
|
||||||
BoxShadow(
|
|
||||||
color: Color.fromRGBO(46, 91, 255, 0.1),
|
|
||||||
offset: Offset.zero, //阴影y轴偏移量
|
|
||||||
blurRadius: 20, //阴影模糊程度
|
|
||||||
spreadRadius: 10, //阴影扩散程度
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
Get.toNamed(Routes.agreementPage, arguments: {"type": AGREEMENT_KEY.PRIVACY_GREEMENT.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),
|
|
||||||
Obx(() {
|
|
||||||
return quickText(localVersion);
|
|
||||||
})
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Positioned(
|
|
||||||
bottom: 50.h,
|
|
||||||
child: InkWell(
|
|
||||||
child: Container(
|
|
||||||
height: 46.h,
|
|
||||||
width: ScreenUtil().screenWidth - 60.w,
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 14.h),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.all(
|
|
||||||
Radius.circular(6.w),
|
|
||||||
),
|
|
||||||
color: Colors.white,
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: const Color.fromRGBO(46, 91, 255, 0.2),
|
|
||||||
offset: Offset(2.w, 2.h), //阴影y轴偏移量
|
|
||||||
blurRadius: 14, //阴影模糊程度
|
|
||||||
spreadRadius: 0.5, //阴影扩散程度
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
Icons.exit_to_app_outlined,
|
|
||||||
size: 13.sp,
|
|
||||||
color: const Color.fromRGBO(148, 163, 182, 1),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
width: 6.w,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'账户注销',
|
|
||||||
style: TextStyle(color: const Color.fromRGBO(148, 163, 182, 1), fontSize: 13.sp),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onTap: () => _showAlertDialog(context),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [Text('APP备案号: ', style: personalInfoTitleStly), quickText('渝ICP备17007225号-4A', size: 14.sp)],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,10 @@ import 'package:making_school_asignment_app/common/job/user_info_detail.dart';
|
||||||
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
|
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
|
||||||
import 'package:making_school_asignment_app/common/store/user_store.dart';
|
import 'package:making_school_asignment_app/common/store/user_store.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/app_upgrade/upgradeLogic.dart';
|
import 'package:making_school_asignment_app/common/utils/app_upgrade/upgradeLogic.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/utils/platform_utils.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/storage.dart';
|
import 'package:making_school_asignment_app/common/utils/storage.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/toast_utils.dart';
|
import 'package:making_school_asignment_app/common/utils/toast_utils.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/global_widget/desktop_scaffold.dart';
|
||||||
import 'package:making_school_asignment_app/page/home_page/children/my_info.dart';
|
import 'package:making_school_asignment_app/page/home_page/children/my_info.dart';
|
||||||
import 'package:making_school_asignment_app/page/home_page/home_view.dart';
|
import 'package:making_school_asignment_app/page/home_page/home_view.dart';
|
||||||
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
|
@ -89,7 +91,9 @@ class _StartPageState extends State<StartPage> with RequestToolMixin {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return PopScope(
|
return PlatformUtils.isDesktop
|
||||||
|
? const DesktopScaffold()
|
||||||
|
: PopScope(
|
||||||
canPop: false,
|
canPop: false,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
body: PageView(
|
body: PageView(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,183 @@
|
||||||
|
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:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/job/student_item.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/global_widget/MyEmptyWidget.dart';
|
||||||
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
|
||||||
|
import 'class_student_logic.dart';
|
||||||
|
|
||||||
|
class ClassStudentDesktopPage extends StatefulWidget {
|
||||||
|
const ClassStudentDesktopPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ClassStudentDesktopPage> createState() => _ClassStudentDesktopPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ClassStudentDesktopPageState extends State<ClassStudentDesktopPage> {
|
||||||
|
final logic = Get.find<ClassStudentLogic>();
|
||||||
|
final state = Get.find<ClassStudentLogic>().state;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: const Color(0xFFF0F2F5),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
_buildHeader(),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(24.r),
|
||||||
|
child: Card(
|
||||||
|
elevation: 2,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.r)),
|
||||||
|
child: Obx(() {
|
||||||
|
return EasyRefresh(
|
||||||
|
controller: logic.refreshController,
|
||||||
|
header: MaterialHeader(),
|
||||||
|
onRefresh: () async {
|
||||||
|
logic.getList();
|
||||||
|
},
|
||||||
|
child: state.studentList.isNotEmpty ? _buildStudentGrid() : const MyEmptyWidget(),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildHeader() {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.all(24.r),
|
||||||
|
color: Colors.white,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Obx(() => Text(
|
||||||
|
state.title.value,
|
||||||
|
style: TextStyle(fontSize: 24.sp, fontWeight: FontWeight.bold, color: const Color(0xFF333333)),
|
||||||
|
)),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => Get.back(),
|
||||||
|
icon: Icon(Icons.close, size: 24.sp, color: Colors.grey[600]),
|
||||||
|
tooltip: '关闭',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildStudentGrid() {
|
||||||
|
return GridView.builder(
|
||||||
|
padding: EdgeInsets.all(16.r),
|
||||||
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisCount: 3,
|
||||||
|
crossAxisSpacing: 16.r,
|
||||||
|
mainAxisSpacing: 16.r,
|
||||||
|
childAspectRatio: 2.5,
|
||||||
|
),
|
||||||
|
itemCount: state.studentList.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
StudentItem item = state.studentList[index];
|
||||||
|
return _buildStudentCard(item);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildStudentCard(StudentItem item) {
|
||||||
|
return Card(
|
||||||
|
elevation: 2,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.r)),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.studentWorkDetailPage, arguments: {
|
||||||
|
'studentName': item.name,
|
||||||
|
'studentId': item.id,
|
||||||
|
'subject': state.subject,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(16.r),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
item.name,
|
||||||
|
style: TextStyle(fontSize: 14.sp, color: const Color(0xFF333333), fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
_buildActionButton(item),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildActionButton(StudentItem item) {
|
||||||
|
if (state.page == 'answerTrajectory') {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(color: const Color(0xFFB2DA93)),
|
||||||
|
borderRadius: BorderRadius.circular(16.r),
|
||||||
|
),
|
||||||
|
child: Text('详情', style: TextStyle(fontSize: 12.sp, color: const Color(0xFFB2DA93))),
|
||||||
|
);
|
||||||
|
} else if (state.page == 'history') {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
borderRadius: BorderRadius.circular(16.r),
|
||||||
|
),
|
||||||
|
child: Text('历史作业', style: TextStyle(fontSize: 12.sp, color: Colors.white)),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return InkWell(
|
||||||
|
onTap: () {
|
||||||
|
logic.setJobReadLevel(item.id, !item.priorityAnnotate);
|
||||||
|
EasyLoading.show(status: 'loading...');
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: item.priorityAnnotate ? const Color(0xFFEBE4FF) : const Color(0xFFE1E1E1),
|
||||||
|
borderRadius: BorderRadius.circular(16.r),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
item.priorityAnnotate ? Icons.star : Icons.star_border,
|
||||||
|
size: 14.r,
|
||||||
|
color: item.priorityAnnotate ? Theme.of(context).primaryColor : Colors.grey,
|
||||||
|
),
|
||||||
|
SizedBox(width: 4.w),
|
||||||
|
Text(
|
||||||
|
'优先批阅',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12.sp,
|
||||||
|
color: item.priorityAnnotate ? Theme.of(context).primaryColor : Colors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
Get.delete<ClassStudentLogic>();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,341 @@
|
||||||
|
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:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/job/student_item.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/utils/utils.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/global_widget/MyEmptyWidget.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/global_widget/ReturnToHomepage.dart';
|
||||||
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
|
||||||
|
import 'class_student_logic.dart';
|
||||||
|
|
||||||
|
class ClassStudentMobilePage extends StatefulWidget {
|
||||||
|
const ClassStudentMobilePage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ClassStudentMobilePage> createState() => _ClassStudentMobilePageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ClassStudentMobilePageState extends State<ClassStudentMobilePage> {
|
||||||
|
final logic = Get.find<ClassStudentLogic>();
|
||||||
|
final state = Get.find<ClassStudentLogic>().state;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return OrientationBuilder(builder: (BuildContext context, Orientation orientation) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: const Color.fromRGBO(245, 245, 245, 1),
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
title: Obx(() {
|
||||||
|
return Text(
|
||||||
|
state.title.value,
|
||||||
|
style: TextStyle(fontSize: 14.sp, color: const Color(0xFF333333)),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
centerTitle: true,
|
||||||
|
leading: IconButton(
|
||||||
|
icon: const Icon(Icons.arrow_back_ios, color: Colors.black),
|
||||||
|
onPressed: () => Get.back(),
|
||||||
|
),
|
||||||
|
actions: const [
|
||||||
|
ReturnToHomepage(),
|
||||||
|
],
|
||||||
|
elevation: 0,
|
||||||
|
),
|
||||||
|
body: Obx(() {
|
||||||
|
return EasyRefresh(
|
||||||
|
firstRefresh: false,
|
||||||
|
taskIndependence: true,
|
||||||
|
controller: logic.refreshController,
|
||||||
|
header: MaterialHeader(),
|
||||||
|
footer: TaurusFooter(),
|
||||||
|
onRefresh: () async {
|
||||||
|
logic.getList();
|
||||||
|
},
|
||||||
|
child: state.studentList.isNotEmpty
|
||||||
|
? Utils.isPad()
|
||||||
|
? GridView(
|
||||||
|
shrinkWrap: true,
|
||||||
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisCount: 2,
|
||||||
|
mainAxisSpacing: 0.r,
|
||||||
|
crossAxisSpacing: 0.r,
|
||||||
|
childAspectRatio: 556 / 90,
|
||||||
|
),
|
||||||
|
children: List.generate(state.studentList.length, (index) {
|
||||||
|
StudentItem item = state.studentList[index];
|
||||||
|
return InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.studentWorkDetailPage, arguments: {
|
||||||
|
'studentName': item.name,
|
||||||
|
'studentId': item.id,
|
||||||
|
'subject': state.subject,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 10.r),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(0.r)),
|
||||||
|
color: Colors.transparent,
|
||||||
|
border: Border(
|
||||||
|
left: BorderSide(
|
||||||
|
width: (index + 1) % 2 == 0 ? 1.r : 0, color: const Color(0xFFA5A5A5)),
|
||||||
|
bottom: BorderSide(width: 1.r, color: const Color(0xFFA5A5A5)))),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
item.name,
|
||||||
|
style: TextStyle(fontSize: 12.sp, color: Theme.of(context).primaryColor),
|
||||||
|
)),
|
||||||
|
state.page == 'answerTrajectory'
|
||||||
|
? Container(
|
||||||
|
height: 20.r,
|
||||||
|
width: 70.r,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(width: 1.r, color: const Color(0xFFB2DA93)),
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(20.r)),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Text('详情',
|
||||||
|
style: TextStyle(fontSize: 10.r, color: const Color(0xFFB2DA93))),
|
||||||
|
))
|
||||||
|
: state.page == 'history'
|
||||||
|
? Container(
|
||||||
|
height: 20.r,
|
||||||
|
width: 70.r,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(20.r))),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
'历史作业',
|
||||||
|
style: TextStyle(fontSize: 10.r, color: Colors.white),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
: item.priorityAnnotate
|
||||||
|
? InkWell(
|
||||||
|
onTap: () {
|
||||||
|
logic.setJobReadLevel(item.id, false);
|
||||||
|
EasyLoading.show(status: 'loading...');
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
height: 20.r,
|
||||||
|
width: 80.r,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(4.r)),
|
||||||
|
color: const Color(0xFFEBE4FF),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(left: 3.r),
|
||||||
|
child: Image.asset(
|
||||||
|
'assets/images/youx_icon_active.png',
|
||||||
|
width: 14.r,
|
||||||
|
height: 14.r,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 2.r, left: 4.r),
|
||||||
|
child: Text(
|
||||||
|
'优先批阅',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 10.sp, color: Theme.of(context).primaryColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
logic.setJobReadLevel(item.id, true);
|
||||||
|
EasyLoading.show(status: 'loading...');
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
height: 20.r,
|
||||||
|
width: 80.r,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(4.r)),
|
||||||
|
color: const Color(0xFFE1E1E1),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(left: 3.r),
|
||||||
|
child: Image.asset(
|
||||||
|
'assets/images/youx_icon_default.png',
|
||||||
|
width: 14.r,
|
||||||
|
height: 14.r,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 2.r, left: 4.r),
|
||||||
|
child: Text(
|
||||||
|
'优先批阅',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 10.sp, color: const Color(0xFF8A9691)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
: Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 14.r, horizontal: 14.r),
|
||||||
|
child: ListView.builder(
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
StudentItem item = state.studentList[index];
|
||||||
|
return InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.studentWorkDetailPage, arguments: {
|
||||||
|
'studentName': item.name,
|
||||||
|
'studentId': item.id,
|
||||||
|
'subject': state.subject,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
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.name,
|
||||||
|
style: TextStyle(fontSize: 12.sp, color: const Color(0xFF4CC793)),
|
||||||
|
)),
|
||||||
|
state.page == 'answerTrajectory'
|
||||||
|
? Container(
|
||||||
|
height: 24.r,
|
||||||
|
width: 72.r,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(width: 1.r, color: const Color(0xFFB2DA93)),
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(20.r)),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: Text('详情',
|
||||||
|
style: TextStyle(fontSize: 10.r, color: const Color(0xFFB2DA93))),
|
||||||
|
))
|
||||||
|
: state.page == 'history'
|
||||||
|
? Container(
|
||||||
|
height: 24.r,
|
||||||
|
width: 82.r,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0xFF4CC793),
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(20.r))),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
'历史作业',
|
||||||
|
style: TextStyle(fontSize: 10.r, color: Colors.white),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
: item.priorityAnnotate
|
||||||
|
? InkWell(
|
||||||
|
onTap: () {
|
||||||
|
logic.setJobReadLevel(item.id, false);
|
||||||
|
EasyLoading.show(status: 'loading...');
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
height: 24.r,
|
||||||
|
width: 82.r,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(4.r)),
|
||||||
|
color: const Color(0xFFB7FFE0),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(left: 3.r),
|
||||||
|
child: Image.asset(
|
||||||
|
'assets/images/youx_icon_active.png',
|
||||||
|
width: 14.r,
|
||||||
|
height: 14.r,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 5.r, left: 4.r),
|
||||||
|
child: Text(
|
||||||
|
'优先批阅',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 10.sp, color: const Color(0xFF4CC793)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
logic.setJobReadLevel(item.id, true);
|
||||||
|
EasyLoading.show(status: 'loading...');
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
height: 24.r,
|
||||||
|
width: 82.r,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(4.r)),
|
||||||
|
color: const Color(0xFFE1E1E1),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(left: 3.r),
|
||||||
|
child: Image.asset(
|
||||||
|
'assets/images/youx_icon_default.png',
|
||||||
|
width: 14.r,
|
||||||
|
height: 14.r,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 5.r, left: 4.r),
|
||||||
|
child: Text(
|
||||||
|
'优先批阅',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 10.sp, color: const Color(0xFF8A9691)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
itemCount: state.studentList.length,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: const MyEmptyWidget(),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
Get.delete<ClassStudentLogic>();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,437 +1,13 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
import 'package:making_school_asignment_app/common/utils/platform_utils.dart';
|
||||||
import 'package:flutter_easyrefresh/easy_refresh.dart';
|
import 'package:making_school_asignment_app/page/home_page/children/class_student/class_student_desktop_view.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:making_school_asignment_app/page/home_page/children/class_student/class_student_mobile_view.dart';
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/job/student_item.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/utils/utils.dart';
|
|
||||||
import 'package:making_school_asignment_app/page/global_widget/MyEmptyWidget.dart';
|
|
||||||
import 'package:making_school_asignment_app/page/global_widget/ReturnToHomepage.dart';
|
|
||||||
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
|
||||||
|
|
||||||
import 'class_student_logic.dart';
|
class ClassStudentPage extends StatelessWidget {
|
||||||
|
const ClassStudentPage({super.key});
|
||||||
class ClassStudentPage extends StatefulWidget {
|
|
||||||
const ClassStudentPage({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<ClassStudentPage> createState() => _ClassStudentPageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ClassStudentPageState extends State<ClassStudentPage> {
|
|
||||||
final logic = Get.find<ClassStudentLogic>();
|
|
||||||
final state = Get.find<ClassStudentLogic>().state;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return OrientationBuilder(
|
return PlatformUtils.isDesktop ? const ClassStudentDesktopPage() : const ClassStudentMobilePage();
|
||||||
builder: (BuildContext context, Orientation orientation){
|
|
||||||
return Scaffold(
|
|
||||||
backgroundColor: const Color.fromRGBO(245, 245, 245, 1),
|
|
||||||
appBar: AppBar(
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
title: Obx(() {
|
|
||||||
return Text(
|
|
||||||
state.title.value,
|
|
||||||
style: TextStyle(fontSize: 14.sp, color: const Color(0xFF333333)),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
centerTitle: true,
|
|
||||||
leading: IconButton(
|
|
||||||
icon: const Icon(Icons.arrow_back_ios, color: Colors.black),
|
|
||||||
onPressed: () => Get.back(),
|
|
||||||
),
|
|
||||||
actions: const [
|
|
||||||
ReturnToHomepage(),
|
|
||||||
],
|
|
||||||
elevation: 0,
|
|
||||||
),
|
|
||||||
body: Obx(() {
|
|
||||||
return EasyRefresh(
|
|
||||||
firstRefresh: false,
|
|
||||||
taskIndependence: true,
|
|
||||||
controller: logic.refreshController,
|
|
||||||
header: MaterialHeader(),
|
|
||||||
footer: TaurusFooter(),
|
|
||||||
onRefresh: () async {
|
|
||||||
logic.getList();
|
|
||||||
},
|
|
||||||
child: state.studentList.isNotEmpty
|
|
||||||
? Utils.isPad()
|
|
||||||
? GridView(
|
|
||||||
shrinkWrap: true,
|
|
||||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
|
||||||
crossAxisCount: 2,
|
|
||||||
mainAxisSpacing: 0.r,
|
|
||||||
crossAxisSpacing: 0.r,
|
|
||||||
childAspectRatio: 556 / 90,
|
|
||||||
),
|
|
||||||
children:
|
|
||||||
List.generate(state.studentList.length, (index) {
|
|
||||||
StudentItem item = state.studentList[index];
|
|
||||||
return InkWell(
|
|
||||||
onTap: () {
|
|
||||||
// RouterManager.router.navigateTo(context,
|
|
||||||
// '${RouterManager.jobPersonalDetailPath}?studentId=${item.studentId}&studentName=${Uri.encodeComponent(item.studentName)}');
|
|
||||||
Get.toNamed(Routes.studentWorkDetailPage,
|
|
||||||
arguments: {
|
|
||||||
'studentName': item.name,
|
|
||||||
'studentId': item.id,
|
|
||||||
'subject':state.subject,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 10.r),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.all(Radius.circular(0.r)),
|
|
||||||
color: Colors.transparent,
|
|
||||||
border: Border(left: BorderSide(width:
|
|
||||||
(index + 1)%2 == 0? 1.r:0,color: const Color(0xFFA5A5A5)),bottom: BorderSide(width: 1.r,color: const Color(0xFFA5A5A5)))
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
item.name,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12.sp,
|
|
||||||
color: Theme.of(context).primaryColor),
|
|
||||||
)),
|
|
||||||
state.page == 'answerTrajectory'
|
|
||||||
? Container(
|
|
||||||
height: 20.r,
|
|
||||||
width: 70.r,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border.all(
|
|
||||||
width: 1.r,
|
|
||||||
color: const Color(0xFFB2DA93)),
|
|
||||||
borderRadius: BorderRadius.all(
|
|
||||||
Radius.circular(20.r)),
|
|
||||||
),
|
|
||||||
child: Center(
|
|
||||||
child: Text('详情',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 10.r,
|
|
||||||
color: Color(0xFFB2DA93))),
|
|
||||||
))
|
|
||||||
: state.page == 'history'
|
|
||||||
? Container(
|
|
||||||
height: 20.r,
|
|
||||||
width: 70.r,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color:
|
|
||||||
Theme.of(context).primaryColor,
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.all(
|
|
||||||
Radius.circular(
|
|
||||||
20.r))),
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
'历史作业',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 10.r,
|
|
||||||
color: Colors.white),
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
: item.priorityAnnotate
|
|
||||||
? InkWell(
|
|
||||||
onTap: () {
|
|
||||||
logic.setJobReadLevel(
|
|
||||||
item.id, false);
|
|
||||||
EasyLoading.show(
|
|
||||||
status: 'loading...');
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
height: 20.r,
|
|
||||||
width: 80.r,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.all(
|
|
||||||
Radius.circular(
|
|
||||||
4.r)),
|
|
||||||
color: const Color(
|
|
||||||
0xFFEBE4FF),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment
|
|
||||||
.start,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding:
|
|
||||||
EdgeInsets.only(
|
|
||||||
left: 3.r),
|
|
||||||
child: Image.asset(
|
|
||||||
'assets/images/youx_icon_active.png',
|
|
||||||
width: 14.r,
|
|
||||||
height: 14.r,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding:
|
|
||||||
EdgeInsets.only(
|
|
||||||
top: 2.r,
|
|
||||||
left: 4.r),
|
|
||||||
child: Text(
|
|
||||||
'优先批阅',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 10.sp,
|
|
||||||
color: Theme.of(context).primaryColor),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
logic.setJobReadLevel(
|
|
||||||
item.id, true);
|
|
||||||
EasyLoading.show(
|
|
||||||
status: 'loading...');
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
height: 20.r,
|
|
||||||
width: 80.r,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.all(
|
|
||||||
Radius.circular(
|
|
||||||
4.r)),
|
|
||||||
color: const Color(
|
|
||||||
0xFFE1E1E1),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment
|
|
||||||
.start,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding:
|
|
||||||
EdgeInsets.only(
|
|
||||||
left: 3.r),
|
|
||||||
child: Image.asset(
|
|
||||||
'assets/images/youx_icon_default.png',
|
|
||||||
width: 14.r,
|
|
||||||
height: 14.r,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding:
|
|
||||||
EdgeInsets.only(
|
|
||||||
top: 2.r,
|
|
||||||
left: 4.r),
|
|
||||||
child: Text(
|
|
||||||
'优先批阅',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 10.sp,
|
|
||||||
color: const Color(
|
|
||||||
0xFF8A9691)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
: Padding(
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 14.r, horizontal: 14.r),
|
|
||||||
child: ListView.builder(
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
StudentItem item = state.studentList[index];
|
|
||||||
return InkWell(
|
|
||||||
onTap: () {
|
|
||||||
// RouterManager.router.navigateTo(context,
|
|
||||||
// '${RouterManager.jobPersonalDetailPath}?studentId=${item.studentId}&studentName=${Uri.encodeComponent(item.studentName)}');
|
|
||||||
Get.toNamed(Routes.studentWorkDetailPage,
|
|
||||||
arguments: {
|
|
||||||
'studentName': item.name,
|
|
||||||
'studentId': item.id,
|
|
||||||
'subject':state.subject,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
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.name,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12.sp,
|
|
||||||
color: const Color(0xFF4CC793)),
|
|
||||||
)),
|
|
||||||
state.page == 'answerTrajectory'
|
|
||||||
? Container(
|
|
||||||
height: 24.r,
|
|
||||||
width: 72.r,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border.all(
|
|
||||||
width: 1.r,
|
|
||||||
color: const Color(0xFFB2DA93)),
|
|
||||||
borderRadius: BorderRadius.all(
|
|
||||||
Radius.circular(20.r)),
|
|
||||||
),
|
|
||||||
child: Center(
|
|
||||||
child: Text('详情',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 10.r,
|
|
||||||
color: Color(0xFFB2DA93))),
|
|
||||||
))
|
|
||||||
: state.page == 'history'
|
|
||||||
? Container(
|
|
||||||
height: 24.r,
|
|
||||||
width: 82.r,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Color(0xFF4CC793),
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.all(
|
|
||||||
Radius.circular(
|
|
||||||
20.r))),
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
'历史作业',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 10.r,
|
|
||||||
color: Colors.white),
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
: item.priorityAnnotate
|
|
||||||
? InkWell(
|
|
||||||
onTap: () {
|
|
||||||
logic.setJobReadLevel(
|
|
||||||
item.id, false);
|
|
||||||
EasyLoading.show(
|
|
||||||
status: 'loading...');
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
height: 24.r,
|
|
||||||
width: 82.r,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.all(
|
|
||||||
Radius.circular(
|
|
||||||
4.r)),
|
|
||||||
color: Color(0xFFB7FFE0),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment
|
|
||||||
.start,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding:
|
|
||||||
EdgeInsets.only(
|
|
||||||
left: 3.r),
|
|
||||||
child: Image.asset(
|
|
||||||
'assets/images/youx_icon_active.png',
|
|
||||||
width: 14.r,
|
|
||||||
height: 14.r,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding:
|
|
||||||
EdgeInsets.only(
|
|
||||||
top: 5.r,
|
|
||||||
left: 4.r),
|
|
||||||
child: Text(
|
|
||||||
'优先批阅',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 10.sp,
|
|
||||||
color: const Color(
|
|
||||||
0xFF4CC793)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
logic.setJobReadLevel(
|
|
||||||
item.id, true);
|
|
||||||
EasyLoading.show(
|
|
||||||
status: 'loading...');
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
height: 24.r,
|
|
||||||
width: 82.r,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.all(
|
|
||||||
Radius.circular(
|
|
||||||
4.r)),
|
|
||||||
color: const Color(
|
|
||||||
0xFFE1E1E1),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment
|
|
||||||
.start,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding:
|
|
||||||
EdgeInsets.only(
|
|
||||||
left: 3.r),
|
|
||||||
child: Image.asset(
|
|
||||||
'assets/images/youx_icon_default.png',
|
|
||||||
width: 14.r,
|
|
||||||
height: 14.r,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding:
|
|
||||||
EdgeInsets.only(
|
|
||||||
top: 5.r,
|
|
||||||
left: 4.r),
|
|
||||||
child: Text(
|
|
||||||
'优先批阅',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 10.sp,
|
|
||||||
color: const Color(
|
|
||||||
0xFF8A9691)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
itemCount: state.studentList.length,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: const MyEmptyWidget(),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
Get.delete<ClassStudentLogic>();
|
|
||||||
super.dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,247 +1,13 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:making_school_asignment_app/common/utils/platform_utils.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:making_school_asignment_app/page/home_page/children/my_info_desktop.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:making_school_asignment_app/page/home_page/children/my_info_mobile.dart';
|
||||||
import 'package:making_school_asignment_app/common/job/user_info_detail.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/store/app_storage_key.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/store/user_store.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/utils/storage.dart';
|
|
||||||
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
|
||||||
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
|
||||||
|
|
||||||
class MyInfo extends StatefulWidget {
|
class MyInfo extends StatelessWidget {
|
||||||
const MyInfo({super.key});
|
const MyInfo({super.key});
|
||||||
|
|
||||||
@override
|
|
||||||
State<MyInfo> createState() => _MyInfoState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _MyInfoState extends State<MyInfo> with AutomaticKeepAliveClientMixin {
|
|
||||||
late Rx<UserInfoDetail?> userInfo = UserStore.to.userDetailInfo;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
|
|
||||||
statusBarIconBrightness: Brightness.light,
|
|
||||||
statusBarColor: Colors.transparent, //状态栏背景颜色
|
|
||||||
// systemStatusBarContrastEnforced: false,
|
|
||||||
));
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确认对话框
|
|
||||||
_showAlertDialog(context1) async {
|
|
||||||
await showDialog(
|
|
||||||
// 表示点击灰色背景的时候是否消失弹出框
|
|
||||||
barrierDismissible: false,
|
|
||||||
context: context1,
|
|
||||||
builder: (context) {
|
|
||||||
return AlertDialog(title: quickText("提示信息"), content: quickText("您确定要退出登录吗?"), actions: <Widget>[
|
|
||||||
TextButton(
|
|
||||||
child: quickText("取消"),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.pop(context, 'Cancle');
|
|
||||||
},
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
child: quickText("确定"),
|
|
||||||
onPressed: () async {
|
|
||||||
try {
|
|
||||||
var pwd = StorageService.to.read(AppStorageKey.pwd.value);
|
|
||||||
var account = StorageService.to.read(AppStorageKey.account.value);
|
|
||||||
|
|
||||||
UserStore.to.erase();
|
|
||||||
await StorageService.to.erase();
|
|
||||||
StorageService.to.write(AppStorageKey.privacyAgreement.value, true);
|
|
||||||
StorageService.to.write(AppStorageKey.account.value, account);
|
|
||||||
StorageService.to.write(AppStorageKey.pwd.value, pwd);
|
|
||||||
Navigator.pop(context, "Ok");
|
|
||||||
Get.offAllNamed(Routes.login);
|
|
||||||
} catch (e) {
|
|
||||||
print(e);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool get wantKeepAlive => true;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
return PlatformUtils.isDesktop ? const MyInfoDesktop() : const MyInfoMobile();
|
||||||
|
|
||||||
final personalInfoTitleStly = TextStyle(
|
|
||||||
color: const Color.fromRGBO(80, 87, 103, 1),
|
|
||||||
fontSize: 13.sp,
|
|
||||||
);
|
|
||||||
final personalInfoValStly = TextStyle(
|
|
||||||
color: const Color.fromRGBO(148, 163, 182, 1),
|
|
||||||
fontSize: 13.sp,
|
|
||||||
);
|
|
||||||
|
|
||||||
return Stack(
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
height: double.infinity,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
height: 220.h,
|
|
||||||
width: double.infinity,
|
|
||||||
decoration: const BoxDecoration(
|
|
||||||
image: DecorationImage(
|
|
||||||
image: AssetImage('assets/images/personal_bg.png'),
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Container(
|
|
||||||
color: const Color.fromRGBO(248, 248, 248, 1),
|
|
||||||
))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SafeArea(
|
|
||||||
child: Scaffold(
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
body: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
height: 150.h,
|
|
||||||
padding: EdgeInsets.only(left: 20.r, right: 20.r),
|
|
||||||
// alignment: Alignment.center,
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Image.asset(
|
|
||||||
'assets/images/default_user_dead.png',
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: 5.w,
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
/*if (tokenState == '' || userState.id == '') {
|
|
||||||
toLoginPage(context);
|
|
||||||
}*/
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
margin: EdgeInsets.only(top: 0.h),
|
|
||||||
child: Text(
|
|
||||||
userInfo.value?.name ?? '请前往登录',
|
|
||||||
style:
|
|
||||||
TextStyle(fontSize: 16.sp, color: const Color(0xFF332A2A), fontWeight: FontWeight.w500),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
_showAlertDialog(context);
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
padding: EdgeInsets.all(2.r),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: const Color.fromRGBO(255, 255, 255, 1),
|
|
||||||
borderRadius: BorderRadius.circular(50.r),
|
|
||||||
),
|
|
||||||
child: Image.asset('assets/images/out_icon.png', fit: BoxFit.cover),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 14.h),
|
|
||||||
Container(
|
|
||||||
margin: EdgeInsets.symmetric(vertical: 5.h, horizontal: 16.w),
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 15.h, horizontal: 16.w),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(6.w)),
|
|
||||||
color: Colors.white,
|
|
||||||
boxShadow: const [
|
|
||||||
BoxShadow(
|
|
||||||
color: Color.fromRGBO(46, 91, 255, 0.1),
|
|
||||||
offset: Offset.zero, //阴影y轴偏移量
|
|
||||||
blurRadius: 20, //阴影模糊程度
|
|
||||||
spreadRadius: 10, //阴影扩散程度
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text('账号', style: personalInfoTitleStly),
|
|
||||||
Text(userInfo.value?.name ?? '请前往登录', style: personalInfoValStly)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
margin: EdgeInsets.symmetric(vertical: 5.h, horizontal: 16.w),
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 15.h, horizontal: 16.w),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(6.w)),
|
|
||||||
color: Colors.white,
|
|
||||||
boxShadow: const [
|
|
||||||
BoxShadow(
|
|
||||||
color: Color.fromRGBO(46, 91, 255, 0.1),
|
|
||||||
offset: Offset.zero, //阴影y轴偏移量
|
|
||||||
blurRadius: 20, //阴影模糊程度
|
|
||||||
spreadRadius: 10, //阴影扩散程度
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text('所在学校', style: personalInfoTitleStly),
|
|
||||||
Text(userInfo.value?.schoolName ?? '', style: personalInfoValStly)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
margin: EdgeInsets.symmetric(vertical: 5.h, horizontal: 16.w),
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 15.h, horizontal: 16.w),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(6.w)),
|
|
||||||
color: Colors.white,
|
|
||||||
boxShadow: const [
|
|
||||||
BoxShadow(
|
|
||||||
color: Color.fromRGBO(46, 91, 255, 0.1),
|
|
||||||
offset: Offset.zero, //阴影y轴偏移量
|
|
||||||
blurRadius: 20, //阴影模糊程度
|
|
||||||
spreadRadius: 10, //阴影扩散程度
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
Get.toNamed(Routes.otherPage);
|
|
||||||
},
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text('其他', style: personalInfoTitleStly),
|
|
||||||
Icon(
|
|
||||||
Icons.arrow_forward_ios,
|
|
||||||
color: const Color.fromRGBO(80, 87, 103, 1),
|
|
||||||
size: 13.sp,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,229 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/job/user_info_detail.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/store/app_storage_key.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/store/user_store.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/utils/storage.dart';
|
||||||
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
|
||||||
|
class MyInfoDesktop extends StatefulWidget {
|
||||||
|
const MyInfoDesktop({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MyInfoDesktop> createState() => _MyInfoDesktopState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MyInfoDesktopState extends State<MyInfoDesktop> with AutomaticKeepAliveClientMixin {
|
||||||
|
late Rx<UserInfoDetail?> userInfo = UserStore.to.userDetailInfo;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get wantKeepAlive => true;
|
||||||
|
|
||||||
|
// 确认对话框
|
||||||
|
_showLogoutDialog(BuildContext context) async {
|
||||||
|
return showDialog<bool>(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('退出登录'),
|
||||||
|
content: const Text('您确定要退出登录吗?'),
|
||||||
|
actions: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
child: const Text('取消'),
|
||||||
|
onPressed: () => Navigator.of(context).pop(false),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
child: const Text('确定'),
|
||||||
|
onPressed: () async {
|
||||||
|
try {
|
||||||
|
var pwd = StorageService.to.read(AppStorageKey.pwd.value);
|
||||||
|
var account = StorageService.to.read(AppStorageKey.account.value);
|
||||||
|
|
||||||
|
UserStore.to.erase();
|
||||||
|
await StorageService.to.erase();
|
||||||
|
StorageService.to.write(AppStorageKey.privacyAgreement.value, true);
|
||||||
|
StorageService.to.write(AppStorageKey.account.value, account);
|
||||||
|
StorageService.to.write(AppStorageKey.pwd.value, pwd);
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
Get.offAllNamed(Routes.login);
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
super.build(context);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: const Color(0xFFF0F2F5),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
padding: EdgeInsets.all(24.r),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_buildHeader(),
|
||||||
|
SizedBox(height: 24.h),
|
||||||
|
_buildUserCard(),
|
||||||
|
SizedBox(height: 16.h),
|
||||||
|
_buildInfoCards(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildHeader() {
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'个人信息',
|
||||||
|
style: TextStyle(fontSize: 24.sp, fontWeight: FontWeight.bold, color: const Color(0xFF333333)),
|
||||||
|
),
|
||||||
|
ElevatedButton.icon(
|
||||||
|
onPressed: () => _showLogoutDialog(context),
|
||||||
|
icon: const Icon(Icons.logout, size: 18),
|
||||||
|
label: const Text('退出登录'),
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: Colors.red[50],
|
||||||
|
foregroundColor: Colors.red[700],
|
||||||
|
elevation: 0,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.r)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildUserCard() {
|
||||||
|
return Card(
|
||||||
|
elevation: 2,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.r)),
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(24.r),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 80.r,
|
||||||
|
height: 80.r,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(40.r),
|
||||||
|
color: Colors.grey[200],
|
||||||
|
),
|
||||||
|
child: Icon(Icons.person, size: 40.r, color: Colors.grey[600]),
|
||||||
|
),
|
||||||
|
SizedBox(width: 24.w),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
userInfo.value?.name ?? '未登录用户',
|
||||||
|
style: TextStyle(fontSize: 20.sp, fontWeight: FontWeight.bold, color: const Color(0xFF333333)),
|
||||||
|
),
|
||||||
|
SizedBox(height: 8.h),
|
||||||
|
Text(
|
||||||
|
userInfo.value?.schoolName ?? '暂无学校信息',
|
||||||
|
style: TextStyle(fontSize: 14.sp, color: Colors.grey[600]),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildInfoCards() {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
_buildInfoCard('账号信息', userInfo.value?.name ?? '请前往登录', Icons.account_circle),
|
||||||
|
SizedBox(height: 12.h),
|
||||||
|
_buildInfoCard('所在学校', userInfo.value?.schoolName ?? '暂无', Icons.school),
|
||||||
|
SizedBox(height: 12.h),
|
||||||
|
_buildClickableInfoCard('其他设置', '点击查看更多选项', Icons.settings, () {
|
||||||
|
Get.toNamed(Routes.otherPage);
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildInfoCard(String title, String value, IconData icon) {
|
||||||
|
return Card(
|
||||||
|
elevation: 1,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.r)),
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(16.r),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(icon, size: 24.r, color: Colors.grey[600]),
|
||||||
|
SizedBox(width: 16.w),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.w500, color: const Color(0xFF333333)),
|
||||||
|
),
|
||||||
|
SizedBox(height: 4.h),
|
||||||
|
Text(
|
||||||
|
value,
|
||||||
|
style: TextStyle(fontSize: 13.sp, color: Colors.grey[600]),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildClickableInfoCard(String title, String subtitle, IconData icon, VoidCallback onTap) {
|
||||||
|
return Card(
|
||||||
|
elevation: 1,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.r)),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: onTap,
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(16.r),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(icon, size: 24.r, color: Colors.grey[600]),
|
||||||
|
SizedBox(width: 16.w),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.w500, color: const Color(0xFF333333)),
|
||||||
|
),
|
||||||
|
SizedBox(height: 4.h),
|
||||||
|
Text(
|
||||||
|
subtitle,
|
||||||
|
style: TextStyle(fontSize: 13.sp, color: Colors.grey[600]),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Icon(Icons.arrow_forward_ios, size: 16.r, color: Colors.grey[400]),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,247 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/job/user_info_detail.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/store/app_storage_key.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/store/user_store.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/utils/storage.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
||||||
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
|
||||||
|
class MyInfoMobile extends StatefulWidget {
|
||||||
|
const MyInfoMobile({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MyInfoMobile> createState() => _MyInfoMobileState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MyInfoMobileState extends State<MyInfoMobile> with AutomaticKeepAliveClientMixin {
|
||||||
|
late Rx<UserInfoDetail?> userInfo = UserStore.to.userDetailInfo;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
|
||||||
|
statusBarIconBrightness: Brightness.light,
|
||||||
|
statusBarColor: Colors.transparent, //状态栏背景颜色
|
||||||
|
// systemStatusBarContrastEnforced: false,
|
||||||
|
));
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认对话框
|
||||||
|
_showAlertDialog(context1) async {
|
||||||
|
await showDialog(
|
||||||
|
// 表示点击灰色背景的时候是否消失弹出框
|
||||||
|
barrierDismissible: false,
|
||||||
|
context: context1,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(title: quickText("提示信息"), content: quickText("您确定要退出登录吗?"), actions: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
child: quickText("取消"),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context, 'Cancle');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
child: quickText("确定"),
|
||||||
|
onPressed: () async {
|
||||||
|
try {
|
||||||
|
var pwd = StorageService.to.read(AppStorageKey.pwd.value);
|
||||||
|
var account = StorageService.to.read(AppStorageKey.account.value);
|
||||||
|
|
||||||
|
UserStore.to.erase();
|
||||||
|
await StorageService.to.erase();
|
||||||
|
StorageService.to.write(AppStorageKey.privacyAgreement.value, true);
|
||||||
|
StorageService.to.write(AppStorageKey.account.value, account);
|
||||||
|
StorageService.to.write(AppStorageKey.pwd.value, pwd);
|
||||||
|
Navigator.pop(context, "Ok");
|
||||||
|
Get.offAllNamed(Routes.login);
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get wantKeepAlive => true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
super.build(context);
|
||||||
|
|
||||||
|
final personalInfoTitleStly = TextStyle(
|
||||||
|
color: const Color.fromRGBO(80, 87, 103, 1),
|
||||||
|
fontSize: 13.sp,
|
||||||
|
);
|
||||||
|
final personalInfoValStly = TextStyle(
|
||||||
|
color: const Color.fromRGBO(148, 163, 182, 1),
|
||||||
|
fontSize: 13.sp,
|
||||||
|
);
|
||||||
|
|
||||||
|
return Stack(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: double.infinity,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
height: 220.h,
|
||||||
|
width: double.infinity,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('assets/images/personal_bg.png'),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
color: const Color.fromRGBO(248, 248, 248, 1),
|
||||||
|
))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SafeArea(
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
body: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
height: 150.h,
|
||||||
|
padding: EdgeInsets.only(left: 20.r, right: 20.r),
|
||||||
|
// alignment: Alignment.center,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Image.asset(
|
||||||
|
'assets/images/default_user_dead.png',
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 5.w,
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
/*if (tokenState == '' || userState.id == '') {
|
||||||
|
toLoginPage(context);
|
||||||
|
}*/
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
margin: EdgeInsets.only(top: 0.h),
|
||||||
|
child: Text(
|
||||||
|
userInfo.value?.name ?? '请前往登录',
|
||||||
|
style:
|
||||||
|
TextStyle(fontSize: 16.sp, color: const Color(0xFF332A2A), fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
_showAlertDialog(context);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(2.r),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color.fromRGBO(255, 255, 255, 1),
|
||||||
|
borderRadius: BorderRadius.circular(50.r),
|
||||||
|
),
|
||||||
|
child: Image.asset('assets/images/out_icon.png', fit: BoxFit.cover),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 14.h),
|
||||||
|
Container(
|
||||||
|
margin: EdgeInsets.symmetric(vertical: 5.h, horizontal: 16.w),
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 15.h, horizontal: 16.w),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(6.w)),
|
||||||
|
color: Colors.white,
|
||||||
|
boxShadow: const [
|
||||||
|
BoxShadow(
|
||||||
|
color: Color.fromRGBO(46, 91, 255, 0.1),
|
||||||
|
offset: Offset.zero, //阴影y轴偏移量
|
||||||
|
blurRadius: 20, //阴影模糊程度
|
||||||
|
spreadRadius: 10, //阴影扩散程度
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text('账号', style: personalInfoTitleStly),
|
||||||
|
Text(userInfo.value?.name ?? '请前往登录', style: personalInfoValStly)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
margin: EdgeInsets.symmetric(vertical: 5.h, horizontal: 16.w),
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 15.h, horizontal: 16.w),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(6.w)),
|
||||||
|
color: Colors.white,
|
||||||
|
boxShadow: const [
|
||||||
|
BoxShadow(
|
||||||
|
color: Color.fromRGBO(46, 91, 255, 0.1),
|
||||||
|
offset: Offset.zero, //阴影y轴偏移量
|
||||||
|
blurRadius: 20, //阴影模糊程度
|
||||||
|
spreadRadius: 10, //阴影扩散程度
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text('所在学校', style: personalInfoTitleStly),
|
||||||
|
Text(userInfo.value?.schoolName ?? '', style: personalInfoValStly)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
margin: EdgeInsets.symmetric(vertical: 5.h, horizontal: 16.w),
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 15.h, horizontal: 16.w),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(6.w)),
|
||||||
|
color: Colors.white,
|
||||||
|
boxShadow: const [
|
||||||
|
BoxShadow(
|
||||||
|
color: Color.fromRGBO(46, 91, 255, 0.1),
|
||||||
|
offset: Offset.zero, //阴影y轴偏移量
|
||||||
|
blurRadius: 20, //阴影模糊程度
|
||||||
|
spreadRadius: 10, //阴影扩散程度
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.otherPage);
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text('其他', style: personalInfoTitleStly),
|
||||||
|
Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
color: const Color.fromRGBO(80, 87, 103, 1),
|
||||||
|
size: 13.sp,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,175 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/mixins/getx_keepalive_widget.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/home_page/children/read_over/widget/annotate_list.dart';
|
||||||
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
|
||||||
|
import 'read_over_logic.dart';
|
||||||
|
|
||||||
|
class ReadOverDesktopPage extends GetxKeepAliveWidget<ReadOverLogic> {
|
||||||
|
const ReadOverDesktopPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget buildContent(BuildContext context, ReadOverLogic controller) {
|
||||||
|
final state = controller.state;
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: const Color(0xFFF0F2F5),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
_buildHeader(context, controller, state),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(24.r),
|
||||||
|
child: Card(
|
||||||
|
elevation: 2,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.r)),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
_buildTabBar(context, controller, state),
|
||||||
|
Expanded(
|
||||||
|
child: Obx(() {
|
||||||
|
return AnnotateList(
|
||||||
|
tabIndex: state.tabIndex.value,
|
||||||
|
assessType: 0,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildHeader(BuildContext context, ReadOverLogic controller, dynamic state) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.all(24.r),
|
||||||
|
color: Colors.white,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'作业批阅',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 24.sp,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: const Color(0xFF333333),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
Get.toNamed(Routes.studentHistoryWorkPage, arguments: {'page': 'set'});
|
||||||
|
},
|
||||||
|
icon: Icon(
|
||||||
|
const IconData(0xe63e, fontFamily: "AlibabaIcon"),
|
||||||
|
color: const Color.fromRGBO(44, 48, 63, 1),
|
||||||
|
size: 24.sp,
|
||||||
|
),
|
||||||
|
tooltip: '设置',
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => Get.back(),
|
||||||
|
icon: Icon(Icons.close, size: 24.sp, color: Colors.grey[600]),
|
||||||
|
tooltip: '关闭',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTabBar(BuildContext context, ReadOverLogic controller, dynamic state) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.all(16.r),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color.fromRGBO(243, 243, 243, 1),
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
),
|
||||||
|
child: TabBar(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
indicatorPadding: EdgeInsets.zero,
|
||||||
|
indicatorWeight: 0,
|
||||||
|
labelPadding: EdgeInsets.symmetric(horizontal: 2.w),
|
||||||
|
controller: controller.tabController,
|
||||||
|
unselectedLabelStyle: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
color: const Color.fromRGBO(69, 83, 100, 1),
|
||||||
|
),
|
||||||
|
labelStyle: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
color: const Color(0xFF8C68FF),
|
||||||
|
),
|
||||||
|
indicator: const UnderlineTabIndicator(
|
||||||
|
borderSide: BorderSide(width: 0, color: Colors.transparent),
|
||||||
|
),
|
||||||
|
onTap: (index) {
|
||||||
|
state.tabIndex.value = index;
|
||||||
|
if (index == 1 && state.completedToRefresh) {
|
||||||
|
state.completedToRefresh = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tabs: <Widget>[
|
||||||
|
Tab(
|
||||||
|
iconMargin: EdgeInsets.zero,
|
||||||
|
height: 34.h,
|
||||||
|
child: Obx(() {
|
||||||
|
return Container(
|
||||||
|
width: 140.w,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: state.tabIndex.value == 0 ? const Color.fromRGBO(255, 255, 255, 1) : null,
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8.r)),
|
||||||
|
),
|
||||||
|
child: quickText(
|
||||||
|
'待批阅',
|
||||||
|
size: 14.sp,
|
||||||
|
color: state.tabIndex.value == 0
|
||||||
|
? Theme.of(context).primaryColor
|
||||||
|
: const Color.fromRGBO(80, 94, 110, 1),
|
||||||
|
fontWeight: state.tabIndex.value == 0 ? FontWeight.bold : null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
iconMargin: EdgeInsets.zero,
|
||||||
|
height: 34.h,
|
||||||
|
child: Obx(() {
|
||||||
|
return Container(
|
||||||
|
width: 140.w,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: state.tabIndex.value == 1 ? const Color.fromRGBO(255, 255, 255, 1) : null,
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8.r)),
|
||||||
|
),
|
||||||
|
child: quickText(
|
||||||
|
'已批阅',
|
||||||
|
size: 14.sp,
|
||||||
|
color: state.tabIndex.value == 1
|
||||||
|
? Theme.of(context).primaryColor
|
||||||
|
: const Color.fromRGBO(80, 94, 110, 1),
|
||||||
|
fontWeight: state.tabIndex.value == 1 ? FontWeight.bold : null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,174 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/mixins/getx_keepalive_widget.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/home_page/children/read_over/widget/annotate_list.dart';
|
||||||
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
|
||||||
|
import 'read_over_logic.dart';
|
||||||
|
|
||||||
|
class ReadOverMobilePage extends GetxKeepAliveWidget<ReadOverLogic> {
|
||||||
|
const ReadOverMobilePage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
|
||||||
|
statusBarColor: Colors.transparent,
|
||||||
|
statusBarIconBrightness: Brightness.dark,
|
||||||
|
systemStatusBarContrastEnforced: false,
|
||||||
|
));
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget buildContent(BuildContext context, ReadOverLogic controller) {
|
||||||
|
final state = controller.state;
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
body: SafeArea(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
height: 60.h,
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 10.w),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () => Get.back(),
|
||||||
|
child: Container(
|
||||||
|
height: 30.h,
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
padding: EdgeInsets.only(left: 10.w),
|
||||||
|
child: Icon(Icons.arrow_back_ios_sharp, size: 16.sp),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 4,
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 2.h),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color.fromRGBO(243, 243, 243, 1),
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
),
|
||||||
|
child: TabBar(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
indicatorPadding: EdgeInsets.zero,
|
||||||
|
indicatorWeight: 0,
|
||||||
|
labelPadding: EdgeInsets.symmetric(horizontal: 2.w),
|
||||||
|
controller: controller.tabController,
|
||||||
|
unselectedLabelStyle: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
color: const Color.fromRGBO(69, 83, 100, 1),
|
||||||
|
),
|
||||||
|
labelStyle: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
color: const Color(0xFF8C68FF),
|
||||||
|
),
|
||||||
|
indicator: const UnderlineTabIndicator(
|
||||||
|
borderSide: BorderSide(width: 0, color: Colors.transparent),
|
||||||
|
),
|
||||||
|
onTap: (index) {
|
||||||
|
state.tabIndex.value = index;
|
||||||
|
if (index == 1 && state.completedToRefresh) {
|
||||||
|
state.completedToRefresh = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tabs: <Widget>[
|
||||||
|
Tab(
|
||||||
|
iconMargin: EdgeInsets.zero,
|
||||||
|
height: 34.h,
|
||||||
|
child: Obx(() {
|
||||||
|
return Container(
|
||||||
|
width: 140.w,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: state.tabIndex.value == 0 ? const Color.fromRGBO(255, 255, 255, 1) : null,
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8.r)),
|
||||||
|
),
|
||||||
|
child: quickText(
|
||||||
|
'待批阅',
|
||||||
|
size: 14.sp,
|
||||||
|
color: state.tabIndex.value == 0
|
||||||
|
? Theme.of(context).primaryColor
|
||||||
|
: const Color.fromRGBO(80, 94, 110, 1),
|
||||||
|
fontWeight: state.tabIndex.value == 0 ? FontWeight.bold : null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
iconMargin: EdgeInsets.zero,
|
||||||
|
height: 34.h,
|
||||||
|
child: Obx(() {
|
||||||
|
return Container(
|
||||||
|
width: 140.w,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: state.tabIndex.value == 1 ? const Color.fromRGBO(255, 255, 255, 1) : null,
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8.r)),
|
||||||
|
),
|
||||||
|
child: quickText(
|
||||||
|
'已批阅',
|
||||||
|
size: 14.sp,
|
||||||
|
color: state.tabIndex.value == 1
|
||||||
|
? Theme.of(context).primaryColor
|
||||||
|
: const Color.fromRGBO(80, 94, 110, 1),
|
||||||
|
fontWeight: state.tabIndex.value == 1 ? FontWeight.bold : null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.studentHistoryWorkPage, arguments: {'page': 'set'});
|
||||||
|
},
|
||||||
|
child: Icon(
|
||||||
|
const IconData(0xe63e, fontFamily: "AlibabaIcon"),
|
||||||
|
color: const Color.fromRGBO(44, 48, 63, 1),
|
||||||
|
size: 24.sp,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
color: const Color.fromRGBO(245, 245, 245, 1),
|
||||||
|
child: Obx(() {
|
||||||
|
return AnnotateList(
|
||||||
|
tabIndex: state.tabIndex.value,
|
||||||
|
assessType: 0,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
Get.delete<ReadOverLogic>();
|
||||||
|
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
|
||||||
|
statusBarColor: Colors.transparent,
|
||||||
|
statusBarIconBrightness: Brightness.light,
|
||||||
|
systemStatusBarContrastEnforced: false,
|
||||||
|
));
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,197 +1,13 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:making_school_asignment_app/common/utils/platform_utils.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:making_school_asignment_app/page/home_page/children/read_over/read_over_desktop_view.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:making_school_asignment_app/page/home_page/children/read_over/read_over_mobile_view.dart';
|
||||||
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
|
||||||
import 'package:making_school_asignment_app/page/home_page/children/read_over/widget/annotate_list.dart';
|
|
||||||
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
|
||||||
|
|
||||||
import 'read_over_logic.dart';
|
class ReadOverPage extends StatelessWidget {
|
||||||
|
|
||||||
class ReadOverPage extends StatefulWidget {
|
|
||||||
const ReadOverPage({super.key});
|
const ReadOverPage({super.key});
|
||||||
|
|
||||||
@override
|
|
||||||
State<ReadOverPage> createState() => _ReadOverPageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ReadOverPageState extends State<ReadOverPage> {
|
|
||||||
final logic = Get.find<ReadOverLogic>();
|
|
||||||
final state = Get.find<ReadOverLogic>().state;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AnnotatedRegion(
|
return PlatformUtils.isDesktop ? const ReadOverDesktopPage() : const ReadOverMobilePage();
|
||||||
value: const SystemUiOverlayStyle(
|
|
||||||
/* systemNavigationBarColor: Color(0xFF000000),
|
|
||||||
systemNavigationBarDividerColor: null,*/
|
|
||||||
statusBarColor: Colors.white,
|
|
||||||
systemNavigationBarDividerColor: null,
|
|
||||||
systemNavigationBarIconBrightness: Brightness.light,
|
|
||||||
statusBarIconBrightness: Brightness.light,
|
|
||||||
statusBarBrightness: Brightness.light,
|
|
||||||
),
|
|
||||||
child: Scaffold(
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
body: OrientationBuilder(
|
|
||||||
builder: (BuildContext context, Orientation orientation) {
|
|
||||||
return Column(
|
|
||||||
children: <Widget>[
|
|
||||||
Container(
|
|
||||||
color: Colors.white,
|
|
||||||
margin: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
|
|
||||||
padding: EdgeInsets.only(bottom: 9.h, top: 4.h),
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
flex: 1,
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
Get.back();
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
height: 30.h,
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
padding: EdgeInsets.only(left: 10.w),
|
|
||||||
child: Icon(
|
|
||||||
Icons.arrow_back_ios_sharp,
|
|
||||||
size: 16.sp,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
Expanded(
|
|
||||||
flex: 4,
|
|
||||||
child: Container(
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 2.h),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: const Color.fromRGBO(243, 243, 243, 1),
|
|
||||||
borderRadius: BorderRadius.circular(8.r),
|
|
||||||
),
|
|
||||||
child: TabBar(
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
indicatorPadding: EdgeInsets.zero,
|
|
||||||
indicatorWeight: 0,
|
|
||||||
labelPadding: EdgeInsets.symmetric(horizontal: 2.w),
|
|
||||||
controller: logic.tabController,
|
|
||||||
unselectedLabelStyle: TextStyle(
|
|
||||||
fontSize: 14.sp,
|
|
||||||
color: const Color.fromRGBO(69, 83, 100, 1),
|
|
||||||
),
|
|
||||||
labelStyle: TextStyle(
|
|
||||||
fontSize: 14.sp,
|
|
||||||
color: const Color(0xFF8C68FF),
|
|
||||||
),
|
|
||||||
// labelColor: const Color.fromRGBO(45, 56, 76, 1),
|
|
||||||
indicator: const UnderlineTabIndicator(
|
|
||||||
borderSide: BorderSide(
|
|
||||||
width: 0, // 设置边界宽度为0,从而去除下划线
|
|
||||||
color: Colors.transparent),
|
|
||||||
),
|
|
||||||
onTap: (index) {
|
|
||||||
state.tabIndex.value = index;
|
|
||||||
if (index == 1 && state.completedToRefresh) {
|
|
||||||
// 已阅卷
|
|
||||||
// _refreshController2.callRefresh();
|
|
||||||
state.completedToRefresh = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tabs: <Widget>[
|
|
||||||
Tab(
|
|
||||||
iconMargin: EdgeInsets.zero,
|
|
||||||
height: 34.h,
|
|
||||||
child: Obx(() {
|
|
||||||
return Container(
|
|
||||||
width: 140.w,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: state.tabIndex.value == 0 ? const Color.fromRGBO(255, 255, 255, 1) : null,
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(8.r)),
|
|
||||||
),
|
|
||||||
child: quickText(
|
|
||||||
'待批阅',
|
|
||||||
size: 14.sp,
|
|
||||||
color: state.tabIndex.value == 0
|
|
||||||
? Theme.of(context).primaryColor
|
|
||||||
: const Color.fromRGBO(80, 94, 110, 1),
|
|
||||||
fontWeight: state.tabIndex.value == 0 ? FontWeight.bold : null,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
Tab(
|
|
||||||
iconMargin: EdgeInsets.zero,
|
|
||||||
height: 34.h,
|
|
||||||
child: Obx(() {
|
|
||||||
return Container(
|
|
||||||
width: 140.w,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: state.tabIndex.value == 1 ? const Color.fromRGBO(255, 255, 255, 1) : null,
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(8.r)),
|
|
||||||
),
|
|
||||||
child: quickText(
|
|
||||||
'已批阅',
|
|
||||||
size: 14.sp,
|
|
||||||
color: state.tabIndex.value == 1
|
|
||||||
? Theme.of(context).primaryColor
|
|
||||||
: const Color.fromRGBO(80, 94, 110, 1),
|
|
||||||
fontWeight: state.tabIndex.value == 1 ? FontWeight.bold : null,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
flex: 1,
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
Get.toNamed(Routes.studentHistoryWorkPage, arguments: {'page': 'set'});
|
|
||||||
},
|
|
||||||
child: Icon(const IconData(0xe63e, fontFamily: "AlibabaIcon"),
|
|
||||||
color: const Color.fromRGBO(44, 48, 63, 1), size: 24.sp),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Container(
|
|
||||||
color: const Color.fromRGBO(245, 245, 245, 1),
|
|
||||||
child: Obx(() {
|
|
||||||
return AnnotateList(
|
|
||||||
tabIndex: state.tabIndex.value,
|
|
||||||
assessType: 0,
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
Get.delete<ReadOverLogic>();
|
|
||||||
logic.homeController.getList();
|
|
||||||
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
|
|
||||||
statusBarColor: Colors.transparent, //状态栏背景颜色
|
|
||||||
statusBarIconBrightness: Brightness.light,
|
|
||||||
systemStatusBarContrastEnforced: false,
|
|
||||||
));
|
|
||||||
super.dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,217 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/mixins/getx_keepalive_widget.dart';
|
||||||
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
|
||||||
|
import 'home_logic.dart';
|
||||||
|
|
||||||
|
class HomeDesktopPage extends GetxKeepAliveWidget<HomeLogic> {
|
||||||
|
const HomeDesktopPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget buildContent(BuildContext context, HomeLogic controller) {
|
||||||
|
final state = controller.state;
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: const Color(0xFFF0F2F5),
|
||||||
|
body: RefreshIndicator(
|
||||||
|
onRefresh: () {
|
||||||
|
state.pageNumber = 1;
|
||||||
|
return Future.microtask(() => controller.getList());
|
||||||
|
},
|
||||||
|
child: CustomScrollView(
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
|
slivers: [
|
||||||
|
SliverPadding(
|
||||||
|
padding: EdgeInsets.all(24.r),
|
||||||
|
sliver: SliverToBoxAdapter(child: _buildHeader(controller)),
|
||||||
|
),
|
||||||
|
SliverPadding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 24.r, vertical: 0),
|
||||||
|
sliver: _buildMenuSliverGrid(state),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildHeader(HomeLogic controller) {
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'我的作业管理',
|
||||||
|
style: TextStyle(fontSize: 24.sp, fontWeight: FontWeight.bold, color: const Color(0xFF333333)),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => controller.getList(),
|
||||||
|
icon: Icon(Icons.refresh, size: 24.sp, color: Colors.grey[600]),
|
||||||
|
tooltip: '刷新数据',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SliverGrid _buildMenuSliverGrid(dynamic state) {
|
||||||
|
final menuItems = [
|
||||||
|
{
|
||||||
|
'bgImg': 'assets/images/home_bg_01.png',
|
||||||
|
'name': '作业批阅',
|
||||||
|
'url': Routes.readOverPage,
|
||||||
|
'isPrimary': true,
|
||||||
|
'value': state.totalCount
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'bgImg': 'assets/images/home_bg_02.png',
|
||||||
|
'name': '知识点掌握',
|
||||||
|
'url': Routes.studentHistoryWorkPage,
|
||||||
|
'page': 'points'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'bgImg': 'assets/images/home_bg_03.png',
|
||||||
|
'name': '学生历史作业',
|
||||||
|
'url': Routes.studentHistoryWorkPage,
|
||||||
|
'page': 'history'
|
||||||
|
},
|
||||||
|
{'bgImg': 'assets/images/home_bg_04.png', 'name': '答题轨迹', 'url': Routes.answerTrajectoryPage},
|
||||||
|
{'bgImg': 'assets/images/home_bg_05.png', 'name': '优先批阅设定', 'url': Routes.studentHistoryWorkPage, 'page': 'set'},
|
||||||
|
];
|
||||||
|
|
||||||
|
int crossAxisCount;
|
||||||
|
final width = Get.width;
|
||||||
|
if (width > 1200) {
|
||||||
|
crossAxisCount = 4;
|
||||||
|
} else if (width > 800) {
|
||||||
|
crossAxisCount = 3;
|
||||||
|
} else {
|
||||||
|
crossAxisCount = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SliverGrid(
|
||||||
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisCount: crossAxisCount,
|
||||||
|
crossAxisSpacing: 16.r,
|
||||||
|
mainAxisSpacing: 16.r,
|
||||||
|
childAspectRatio: 1.5,
|
||||||
|
),
|
||||||
|
delegate: SliverChildBuilderDelegate(
|
||||||
|
(context, index) {
|
||||||
|
final item = menuItems[index];
|
||||||
|
if (item['value'] is RxInt) {
|
||||||
|
return Obx(() => _MenuItem(
|
||||||
|
bgImg: item['bgImg'] as String,
|
||||||
|
name: item['name'] as String,
|
||||||
|
url: item['url'] as String,
|
||||||
|
page: item['page'] as String?,
|
||||||
|
isPrimary: item['isPrimary'] as bool? ?? false,
|
||||||
|
value: (item['value'] as RxInt).value > 0 ? (item['value'] as RxInt).value.toString() : null,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return _MenuItem(
|
||||||
|
bgImg: item['bgImg'] as String,
|
||||||
|
name: item['name'] as String,
|
||||||
|
url: item['url'] as String,
|
||||||
|
page: item['page'] as String?,
|
||||||
|
isPrimary: item['isPrimary'] as bool? ?? false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
childCount: menuItems.length,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MenuItem extends StatefulWidget {
|
||||||
|
final String bgImg;
|
||||||
|
final String name;
|
||||||
|
final String? value;
|
||||||
|
final String url;
|
||||||
|
final String? page;
|
||||||
|
final bool isPrimary;
|
||||||
|
|
||||||
|
const _MenuItem({
|
||||||
|
required this.bgImg,
|
||||||
|
required this.name,
|
||||||
|
this.value,
|
||||||
|
required this.url,
|
||||||
|
this.page,
|
||||||
|
this.isPrimary = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
__MenuItemState createState() => __MenuItemState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class __MenuItemState extends State<_MenuItem> {
|
||||||
|
bool _isHovered = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MouseRegion(
|
||||||
|
onEnter: (_) => setState(() => _isHovered = true),
|
||||||
|
onExit: (_) => setState(() => _isHovered = false),
|
||||||
|
cursor: SystemMouseCursors.click,
|
||||||
|
child: Card(
|
||||||
|
elevation: _isHovered ? 8.0 : 2.0,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.r)),
|
||||||
|
shadowColor: Colors.black.withOpacity(0.1),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () => Get.toNamed(widget.url, arguments: {'page': widget.page ?? ''}),
|
||||||
|
borderRadius: BorderRadius.circular(12.r),
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(16.r),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(12.r),
|
||||||
|
gradient: widget.isPrimary ? const LinearGradient(colors: [Color(0xFF667eea), Color(0xFF764ba2)]) : null,
|
||||||
|
color: widget.isPrimary ? null : Colors.white,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
widget.name,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
color: widget.isPrimary ? Colors.white : const Color(0xFF2C2C2C),
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (widget.value != null && widget.value!.isNotEmpty)
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 4.h),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: widget.isPrimary ? Colors.white : const Color(0xFFFF6969),
|
||||||
|
borderRadius: BorderRadius.circular(12.r),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
widget.value!,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12.sp,
|
||||||
|
color: widget.isPrimary ? const Color(0xFFFF6969) : Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Icon(
|
||||||
|
Icons.arrow_forward,
|
||||||
|
size: 16.sp,
|
||||||
|
color: widget.isPrimary ? Colors.white70 : Colors.grey[400],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,436 @@
|
||||||
|
import 'package:badges/badges.dart' as badges;
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_easyrefresh/easy_refresh.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:functional_widget_annotation/functional_widget_annotation.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/mixins/getx_keepalive_widget.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/utils/utils.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
||||||
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
|
||||||
|
import 'home_logic.dart';
|
||||||
|
|
||||||
|
part 'home_mobile_view.g.dart';
|
||||||
|
|
||||||
|
class HomeMobilePage extends GetxKeepAliveWidget<HomeLogic> {
|
||||||
|
const HomeMobilePage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
|
||||||
|
statusBarColor: Colors.transparent, //状态栏背景颜色
|
||||||
|
statusBarIconBrightness: Brightness.light,
|
||||||
|
systemStatusBarContrastEnforced: false,
|
||||||
|
));
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget buildContent(context, controller) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
body: OrientationBuilder(
|
||||||
|
builder: (BuildContext context, Orientation orientation) {
|
||||||
|
final state = controller.state;
|
||||||
|
return EasyRefresh(
|
||||||
|
firstRefresh: false,
|
||||||
|
taskIndependence: true,
|
||||||
|
enableControlFinishLoad: true,
|
||||||
|
controller: controller.refreshController,
|
||||||
|
header: MaterialHeader(),
|
||||||
|
onRefresh: () async {
|
||||||
|
state.pageNumber = 1;
|
||||||
|
return controller.getList();
|
||||||
|
},
|
||||||
|
child: CustomScrollView(
|
||||||
|
slivers: [
|
||||||
|
// 顶部横幅区域
|
||||||
|
SliverAppBar(
|
||||||
|
expandedHeight: 300.h,
|
||||||
|
floating: false,
|
||||||
|
pinned: false,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
|
background: Image.asset(
|
||||||
|
'assets/images/home_banner.png',
|
||||||
|
width: Get.width,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// 主要内容区域
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 0, horizontal: 20.r),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.only(topLeft: Radius.circular(30.r), topRight: Radius.circular(30.r)),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SizedBox(height: 20.r),
|
||||||
|
// 标题区域
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.assignment_outlined,
|
||||||
|
size: 24.sp,
|
||||||
|
color: const Color(0xFF4F4F4F),
|
||||||
|
),
|
||||||
|
SizedBox(width: 8.r),
|
||||||
|
Text(
|
||||||
|
'我的作业管理',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 22.sp, color: const Color(0xFF2C2C2C), fontWeight: FontWeight.w700),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
// 刷新按钮
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => controller.refreshController.callRefresh(),
|
||||||
|
icon: Icon(
|
||||||
|
Icons.refresh,
|
||||||
|
size: 20.sp,
|
||||||
|
color: const Color(0xFF4F4F4F),
|
||||||
|
),
|
||||||
|
tooltip: '刷新数据',
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(height: 24.r),
|
||||||
|
// 功能菜单网格
|
||||||
|
_buildMenuGrid(context, state),
|
||||||
|
SizedBox(height: 20.r),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildMenuGrid(BuildContext context, dynamic state) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
// 第一行
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Obx(() => $MenuItem(
|
||||||
|
bgImg: 'assets/images/home_bg_01.png',
|
||||||
|
name: '作业批阅',
|
||||||
|
value: state.totalCount.value > 0 ? state.totalCount.value.toString() : null,
|
||||||
|
url: Routes.readOverPage,
|
||||||
|
isPrimary: true,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
SizedBox(width: 16.r),
|
||||||
|
const Expanded(
|
||||||
|
child: $MenuItem(
|
||||||
|
bgImg: 'assets/images/home_bg_02.png',
|
||||||
|
name: '知识点掌握',
|
||||||
|
url: Routes.studentHistoryWorkPage,
|
||||||
|
page: 'points',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 16.r),
|
||||||
|
// 第二行
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
const Expanded(
|
||||||
|
child: $MenuItem(
|
||||||
|
bgImg: 'assets/images/home_bg_03.png',
|
||||||
|
name: '学生历史作业',
|
||||||
|
url: Routes.studentHistoryWorkPage,
|
||||||
|
page: 'history',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 16.r),
|
||||||
|
const Expanded(
|
||||||
|
child: $MenuItem(bgImg: 'assets/images/home_bg_04.png', name: '答题轨迹', url: Routes.answerTrajectoryPage),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 16.r),
|
||||||
|
// 第三行
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
const Expanded(
|
||||||
|
child: $MenuItem(
|
||||||
|
bgImg: 'assets/images/home_bg_05.png',
|
||||||
|
name: '优先批阅设定',
|
||||||
|
url: Routes.studentHistoryWorkPage,
|
||||||
|
page: 'set',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 16.r),
|
||||||
|
// 占位空间
|
||||||
|
const Expanded(child: SizedBox()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@swidget
|
||||||
|
Widget $menuItem({
|
||||||
|
required String bgImg,
|
||||||
|
required String name,
|
||||||
|
String? value,
|
||||||
|
required String url,
|
||||||
|
String? page,
|
||||||
|
bool isPrimary = false,
|
||||||
|
}) {
|
||||||
|
return Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(url, arguments: {'page': page ?? ''});
|
||||||
|
},
|
||||||
|
borderRadius: BorderRadius.circular(12.r),
|
||||||
|
child: Semantics(
|
||||||
|
label: '$name${value != null ? ',待处理数量:$value' : ''}',
|
||||||
|
hint: '点击进入$name页面',
|
||||||
|
button: true,
|
||||||
|
child: Container(
|
||||||
|
width: (Get.width - 60.r) / 2,
|
||||||
|
height: (Get.width - 60.r) / 2 * 86 / 164,
|
||||||
|
padding: EdgeInsets.all(16.r),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(12.r),
|
||||||
|
gradient: isPrimary
|
||||||
|
? const LinearGradient(
|
||||||
|
begin: Alignment.topLeft,
|
||||||
|
end: Alignment.bottomRight,
|
||||||
|
colors: [
|
||||||
|
Color(0xFF667eea),
|
||||||
|
Color(0xFF764ba2),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
color: isPrimary ? null : Colors.white,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.08),
|
||||||
|
blurRadius: 8,
|
||||||
|
offset: const Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
image: !isPrimary
|
||||||
|
? DecorationImage(
|
||||||
|
image: AssetImage(bgImg),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
colorFilter: ColorFilter.mode(
|
||||||
|
Colors.white.withOpacity(0.8),
|
||||||
|
BlendMode.srcATop,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
name,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
color: isPrimary ? Colors.white : const Color(0xFF2C2C2C),
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (value != null && value != '')
|
||||||
|
Semantics(
|
||||||
|
label: '待处理数量:$value',
|
||||||
|
child: Container(
|
||||||
|
width: 20.r,
|
||||||
|
height: 20.r,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: isPrimary ? Colors.white : const Color(0xFFFF6969),
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(10.r)),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
value,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 10.sp,
|
||||||
|
color: isPrimary ? const Color(0xFFFF6969) : Colors.white,
|
||||||
|
fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
if (isPrimary)
|
||||||
|
Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
size: 14.sp,
|
||||||
|
color: Colors.white,
|
||||||
|
)
|
||||||
|
else
|
||||||
|
Image.asset(
|
||||||
|
'assets/images/home_right_icon.png',
|
||||||
|
width: 16.r,
|
||||||
|
height: 16.r,
|
||||||
|
semanticLabel: '进入图标',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class EntranceModel extends Object {
|
||||||
|
String title;
|
||||||
|
String image;
|
||||||
|
String navigationUrl;
|
||||||
|
String? page;
|
||||||
|
|
||||||
|
EntranceModel({required this.title, required this.image, required this.navigationUrl, this.page});
|
||||||
|
}
|
||||||
|
|
||||||
|
@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!)),
|
||||||
|
// const Expanded(flex: 1, child: SizedBox()),
|
||||||
|
SizedBox(width: ScreenUtil().screenWidth / 30),
|
||||||
|
Expanded(flex: 9, child: $TermItem(items[1], data)),
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
double theHeight = ScreenUtil().screenWidth / 30 + 54.h * 2;
|
||||||
|
childWidget = Row(
|
||||||
|
children: [
|
||||||
|
Expanded(child: $TermItem(items[0], data!, theHeight: theHeight)),
|
||||||
|
SizedBox(width: ScreenUtil().screenWidth / 30),
|
||||||
|
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: () {
|
||||||
|
Get.toNamed(e.navigationUrl, arguments: {'page': e.page ?? ''});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 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: const badges.BadgeAnimation.rotation(
|
||||||
|
animationDuration: Duration(seconds: 1),
|
||||||
|
colorChangeAnimationDuration: Duration(seconds: 1),
|
||||||
|
loopAnimation: false,
|
||||||
|
curve: Curves.fastOutSlowIn,
|
||||||
|
colorChangeAnimationCurve: Curves.easeInCubic,
|
||||||
|
),
|
||||||
|
badgeStyle: badges.BadgeStyle(
|
||||||
|
badgeColor: const 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: Utils.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: const 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: const Color.fromRGBO(79, 79, 79, 1), fontWeight: FontWeight.w500),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,474 +1,13 @@
|
||||||
import 'package:badges/badges.dart' as badges;
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:making_school_asignment_app/common/utils/platform_utils.dart';
|
||||||
import 'package:flutter_easyrefresh/easy_refresh.dart';
|
import 'package:making_school_asignment_app/page/home_page/home_desktop_view.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:making_school_asignment_app/page/home_page/home_mobile_view.dart';
|
||||||
import 'package:functional_widget_annotation/functional_widget_annotation.dart';
|
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/mixins/getx_keepalive_widget.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/utils/utils.dart';
|
|
||||||
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
|
||||||
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
|
||||||
|
|
||||||
import 'home_logic.dart';
|
class HomePage extends StatelessWidget {
|
||||||
|
|
||||||
part 'home_view.g.dart';
|
|
||||||
|
|
||||||
class HomePage extends GetxKeepAliveWidget<HomeLogic> {
|
|
||||||
const HomePage({super.key});
|
const HomePage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
Widget build(BuildContext context) {
|
||||||
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
|
return PlatformUtils.isDesktop ? const HomeDesktopPage() : const HomeMobilePage();
|
||||||
statusBarColor: Colors.transparent, //状态栏背景颜色
|
|
||||||
statusBarIconBrightness: Brightness.light,
|
|
||||||
systemStatusBarContrastEnforced: false,
|
|
||||||
));
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget buildContent(context, controller) {
|
|
||||||
return Scaffold(
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
body: OrientationBuilder(
|
|
||||||
builder: (BuildContext context, Orientation orientation) {
|
|
||||||
final state = controller.state;
|
|
||||||
return EasyRefresh(
|
|
||||||
firstRefresh: false,
|
|
||||||
taskIndependence: true,
|
|
||||||
enableControlFinishLoad: true,
|
|
||||||
controller: controller.refreshController,
|
|
||||||
header: MaterialHeader(),
|
|
||||||
onRefresh: () async {
|
|
||||||
state.pageNumber = 1;
|
|
||||||
return controller.getList();
|
|
||||||
},
|
|
||||||
child: CustomScrollView(
|
|
||||||
slivers: [
|
|
||||||
// 顶部横幅区域
|
|
||||||
SliverAppBar(
|
|
||||||
expandedHeight: 300.h,
|
|
||||||
floating: false,
|
|
||||||
pinned: false,
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
flexibleSpace: FlexibleSpaceBar(
|
|
||||||
background: Image.asset(
|
|
||||||
'assets/images/home_banner.png',
|
|
||||||
width: Get.width,
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// 主要内容区域
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Container(
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 0, horizontal: 20.r),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white,
|
|
||||||
borderRadius: BorderRadius.only(topLeft: Radius.circular(30.r), topRight: Radius.circular(30.r)),
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
SizedBox(height: 20.r),
|
|
||||||
// 标题区域
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
Icons.assignment_outlined,
|
|
||||||
size: 24.sp,
|
|
||||||
color: const Color(0xFF4F4F4F),
|
|
||||||
),
|
|
||||||
SizedBox(width: 8.r),
|
|
||||||
Text(
|
|
||||||
'我的作业管理',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 22.sp, color: const Color(0xFF2C2C2C), fontWeight: FontWeight.w700),
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
// 刷新按钮
|
|
||||||
IconButton(
|
|
||||||
onPressed: () => controller.refreshController.callRefresh(),
|
|
||||||
icon: Icon(
|
|
||||||
Icons.refresh,
|
|
||||||
size: 20.sp,
|
|
||||||
color: const Color(0xFF4F4F4F),
|
|
||||||
),
|
|
||||||
tooltip: '刷新数据',
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
|
|
||||||
SizedBox(height: 24.r),
|
|
||||||
// 功能菜单网格
|
|
||||||
_buildMenuGrid(context, state),
|
|
||||||
SizedBox(height: 20.r),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildStatCard(String title, String value, Color color, IconData icon) {
|
|
||||||
return Container(
|
|
||||||
padding: EdgeInsets.all(12.r),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white,
|
|
||||||
borderRadius: BorderRadius.circular(8.r),
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black.withOpacity(0.05),
|
|
||||||
blurRadius: 4,
|
|
||||||
offset: const Offset(0, 2),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Icon(icon, color: color, size: 20.sp),
|
|
||||||
SizedBox(height: 4.r),
|
|
||||||
Text(
|
|
||||||
value,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 18.sp,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: color,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
title,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12.sp,
|
|
||||||
color: const Color(0xFF6C757D),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildMenuGrid(BuildContext context, dynamic state) {
|
|
||||||
return Column(
|
|
||||||
children: [
|
|
||||||
// 第一行
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Obx(() => $MenuItem(
|
|
||||||
bgImg: 'assets/images/home_bg_01.png',
|
|
||||||
name: '作业批阅',
|
|
||||||
value: state.totalCount.value > 0 ? state.totalCount.value.toString() : null,
|
|
||||||
url: Routes.readOverPage,
|
|
||||||
isPrimary: true,
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
SizedBox(width: 16.r),
|
|
||||||
const Expanded(
|
|
||||||
child: $MenuItem(
|
|
||||||
bgImg: 'assets/images/home_bg_02.png',
|
|
||||||
name: '知识点掌握',
|
|
||||||
url: Routes.studentHistoryWorkPage,
|
|
||||||
page: 'points',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox(height: 16.r),
|
|
||||||
// 第二行
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
const Expanded(
|
|
||||||
child: $MenuItem(
|
|
||||||
bgImg: 'assets/images/home_bg_03.png',
|
|
||||||
name: '学生历史作业',
|
|
||||||
url: Routes.studentHistoryWorkPage,
|
|
||||||
page: 'history',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: 16.r),
|
|
||||||
const Expanded(
|
|
||||||
child: $MenuItem(bgImg: 'assets/images/home_bg_04.png', name: '答题轨迹', url: Routes.answerTrajectoryPage),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox(height: 16.r),
|
|
||||||
// 第三行
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
const Expanded(
|
|
||||||
child: $MenuItem(
|
|
||||||
bgImg: 'assets/images/home_bg_05.png',
|
|
||||||
name: '优先批阅设定',
|
|
||||||
url: Routes.studentHistoryWorkPage,
|
|
||||||
page: 'set',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: 16.r),
|
|
||||||
// 占位空间
|
|
||||||
const Expanded(child: SizedBox()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@swidget
|
|
||||||
Widget $menuItem({
|
|
||||||
required String bgImg,
|
|
||||||
required String name,
|
|
||||||
String? value,
|
|
||||||
required String url,
|
|
||||||
String? page,
|
|
||||||
bool isPrimary = false,
|
|
||||||
}) {
|
|
||||||
return Material(
|
|
||||||
color: Colors.transparent,
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
Get.toNamed(url, arguments: {'page': page ?? ''});
|
|
||||||
},
|
|
||||||
borderRadius: BorderRadius.circular(12.r),
|
|
||||||
child: Semantics(
|
|
||||||
label: '$name${value != null ? ',待处理数量:$value' : ''}',
|
|
||||||
hint: '点击进入$name页面',
|
|
||||||
button: true,
|
|
||||||
child: Container(
|
|
||||||
width: (Get.width - 60.r) / 2,
|
|
||||||
height: (Get.width - 60.r) / 2 * 86 / 164,
|
|
||||||
padding: EdgeInsets.all(16.r),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(12.r),
|
|
||||||
gradient: isPrimary
|
|
||||||
? const LinearGradient(
|
|
||||||
begin: Alignment.topLeft,
|
|
||||||
end: Alignment.bottomRight,
|
|
||||||
colors: [
|
|
||||||
Color(0xFF667eea),
|
|
||||||
Color(0xFF764ba2),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
color: isPrimary ? null : Colors.white,
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black.withOpacity(0.08),
|
|
||||||
blurRadius: 8,
|
|
||||||
offset: const Offset(0, 2),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
image: !isPrimary
|
|
||||||
? DecorationImage(
|
|
||||||
image: AssetImage(bgImg),
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
colorFilter: ColorFilter.mode(
|
|
||||||
Colors.white.withOpacity(0.8),
|
|
||||||
BlendMode.srcATop,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
name,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14.sp,
|
|
||||||
color: isPrimary ? Colors.white : const Color(0xFF2C2C2C),
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
maxLines: 2,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (value != null && value != '')
|
|
||||||
Semantics(
|
|
||||||
label: '待处理数量:$value',
|
|
||||||
child: Container(
|
|
||||||
width: 20.r,
|
|
||||||
height: 20.r,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: isPrimary ? Colors.white : const Color(0xFFFF6969),
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(10.r)),
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
value,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 10.sp,
|
|
||||||
color: isPrimary ? const Color(0xFFFF6969) : Colors.white,
|
|
||||||
fontWeight: FontWeight.w600),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
if (isPrimary)
|
|
||||||
Icon(
|
|
||||||
Icons.arrow_forward_ios,
|
|
||||||
size: 14.sp,
|
|
||||||
color: Colors.white,
|
|
||||||
)
|
|
||||||
else
|
|
||||||
Image.asset(
|
|
||||||
'assets/images/home_right_icon.png',
|
|
||||||
width: 16.r,
|
|
||||||
height: 16.r,
|
|
||||||
semanticLabel: '进入图标',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class EntranceModel extends Object {
|
|
||||||
String title;
|
|
||||||
String image;
|
|
||||||
String navigationUrl;
|
|
||||||
String? page;
|
|
||||||
|
|
||||||
EntranceModel({required this.title, required this.image, required this.navigationUrl, this.page});
|
|
||||||
}
|
|
||||||
|
|
||||||
@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!)),
|
|
||||||
// const Expanded(flex: 1, child: SizedBox()),
|
|
||||||
SizedBox(width: ScreenUtil().screenWidth / 30),
|
|
||||||
Expanded(flex: 9, child: $TermItem(items[1], data)),
|
|
||||||
]);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
double theHeight = ScreenUtil().screenWidth / 30 + 54.h * 2;
|
|
||||||
childWidget = Row(
|
|
||||||
children: [
|
|
||||||
Expanded(child: $TermItem(items[0], data!, theHeight: theHeight)),
|
|
||||||
SizedBox(width: ScreenUtil().screenWidth / 30),
|
|
||||||
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: () {
|
|
||||||
Get.toNamed(e.navigationUrl, arguments: {'page': e.page ?? ''});
|
|
||||||
},
|
|
||||||
|
|
||||||
// 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: const badges.BadgeAnimation.rotation(
|
|
||||||
animationDuration: Duration(seconds: 1),
|
|
||||||
colorChangeAnimationDuration: Duration(seconds: 1),
|
|
||||||
loopAnimation: false,
|
|
||||||
curve: Curves.fastOutSlowIn,
|
|
||||||
colorChangeAnimationCurve: Curves.easeInCubic,
|
|
||||||
),
|
|
||||||
badgeStyle: badges.BadgeStyle(
|
|
||||||
badgeColor: const 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: Utils.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: const 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: const Color.fromRGBO(79, 79, 79, 1), fontWeight: FontWeight.w500),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
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:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/const_text.dart';
|
||||||
|
|
||||||
|
class AgreementDesktopPage extends StatelessWidget {
|
||||||
|
const AgreementDesktopPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
AGREEMENT_KEY type = AGREEMENT_KEY.values.byName(Get.arguments['type']);
|
||||||
|
AgreementClass agreement = AGREEMENT_MAP[type]!;
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: const Color(0xFFF0F2F5),
|
||||||
|
body: Center(
|
||||||
|
child: Container(
|
||||||
|
width: 800.w,
|
||||||
|
height: 600.h,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.1),
|
||||||
|
blurRadius: 20,
|
||||||
|
offset: const Offset(0, 10),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
AppBar(
|
||||||
|
title: Text(agreement.title),
|
||||||
|
centerTitle: true,
|
||||||
|
automaticallyImplyLeading: false,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.vertical(
|
||||||
|
top: Radius.circular(8.r),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
padding: EdgeInsets.all(24.r),
|
||||||
|
child: HtmlWidget(agreement.richText),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.all(16.r),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () => Get.back(),
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
minimumSize: Size(120.w, 50.h),
|
||||||
|
),
|
||||||
|
child: const Text('关闭'),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
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:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/const_text.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
||||||
|
|
||||||
|
// 协议富文本
|
||||||
|
class AgreementMobilePage extends StatelessWidget {
|
||||||
|
const AgreementMobilePage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
AGREEMENT_KEY type = AGREEMENT_KEY.values.byName(Get.arguments['type']);
|
||||||
|
AgreementClass agreement = AGREEMENT_MAP[type]!;
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Theme.of(context).primaryColor,
|
||||||
|
title: quickText(agreement.title, color: Colors.white),
|
||||||
|
),
|
||||||
|
body: ListView(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 14.w, vertical: 8.h),
|
||||||
|
children: [
|
||||||
|
HtmlWidget(agreement.richText, textStyle: const TextStyle(color: Colors.black)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,29 +1,13 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:making_school_asignment_app/common/utils/platform_utils.dart';
|
||||||
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
|
import 'package:making_school_asignment_app/page/login_page/children/agreement_desktop.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:making_school_asignment_app/page/login_page/children/agreement_mobile.dart';
|
||||||
import 'package:making_school_asignment_app/common/const_text.dart';
|
|
||||||
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
|
||||||
|
|
||||||
// 协议富文本
|
|
||||||
class AgreementPage extends StatelessWidget {
|
class AgreementPage extends StatelessWidget {
|
||||||
const AgreementPage({super.key});
|
const AgreementPage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
AGREEMENT_KEY type = AGREEMENT_KEY.values.byName(Get.arguments['type']);
|
return PlatformUtils.isDesktop ? const AgreementDesktopPage() : const AgreementMobilePage();
|
||||||
AgreementClass agreement = AGREEMENT_MAP[type]!;
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
backgroundColor: Theme.of(context).primaryColor,
|
|
||||||
title: quickText(agreement.title, color: Colors.white),
|
|
||||||
),
|
|
||||||
body: ListView(
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 14.w, vertical: 8.h),
|
|
||||||
children: [
|
|
||||||
HtmlWidget(agreement.richText, textStyle: const TextStyle(color: Colors.black)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,291 +1,13 @@
|
||||||
import 'package:dio/dio.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:making_school_asignment_app/common/utils/platform_utils.dart';
|
||||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
import 'package:making_school_asignment_app/page/login_page/children/register_desktop.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:making_school_asignment_app/page/login_page/children/register_mobile.dart';
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/const_text.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/job/user_register_params.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/utils/toast_utils.dart';
|
|
||||||
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
|
||||||
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
|
||||||
|
|
||||||
/// 注册页面
|
class Register extends StatelessWidget {
|
||||||
class Register extends StatefulWidget {
|
|
||||||
const Register({super.key});
|
const Register({super.key});
|
||||||
|
|
||||||
@override
|
|
||||||
State<Register> createState() => _RegisterState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _RegisterState extends State<Register> with RequestToolMixin {
|
|
||||||
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) {
|
|
||||||
Future.delayed(Duration.zero, () => 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 (userPwd.length < 6) return toMsg('密码长度不得少于6位');
|
|
||||||
if (!readAgreement) return toMsg('请勾选我已阅读用户协议和隐私协议');
|
|
||||||
EasyLoading.show(status: 'loading...');
|
|
||||||
var resultData = await getClient().toRegister(UserRegisterParams(account: userName, password: userPwd));
|
|
||||||
print(resultData);
|
|
||||||
// if (resultData.success) return toMsg(resultData.message ?? '注册失败,请重试');
|
|
||||||
ToastUtils.showSuccess('注册成功,请登录');
|
|
||||||
// 跳转登录页
|
|
||||||
Future.delayed(Duration.zero, () => Get.back());
|
|
||||||
} catch (e) {
|
|
||||||
setState(() => canLogin = true);
|
|
||||||
} finally {
|
|
||||||
EasyLoading.dismiss();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _showPassword() {
|
|
||||||
setState(() {
|
|
||||||
_isShowPwd = !_isShowPwd;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return PlatformUtils.isDesktop ? const RegisterDesktop() : const RegisterMobile();
|
||||||
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/register_bg.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/login_logo_icon.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: (_) => 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 ? Theme.of(context).primaryColor : Colors.grey,
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: const Color.fromRGBO(76, 199, 147, 0.5),
|
|
||||||
offset: Offset(4.w, 6.h), //阴影y轴偏移量
|
|
||||||
blurRadius: 10, //阴影模糊程度
|
|
||||||
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: () {
|
|
||||||
Get.toNamed(Routes.agreementPage, arguments: {"type": AGREEMENT_KEY.USER_AGREEMENT.name});
|
|
||||||
},
|
|
||||||
child: quickText(
|
|
||||||
'《用户协议》',
|
|
||||||
size: 12.sp,
|
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
Get.toNamed(Routes.agreementPage, arguments: {"type": AGREEMENT_KEY.PRIVACY_GREEMENT.name});
|
|
||||||
},
|
|
||||||
child: quickText(
|
|
||||||
'《隐私协议》',
|
|
||||||
size: 12.sp,
|
|
||||||
color:Theme.of(context).primaryColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
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),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,207 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/const_text.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/job/user_register_params.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/utils/toast_utils.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
||||||
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
|
||||||
|
class RegisterDesktop extends StatefulWidget {
|
||||||
|
const RegisterDesktop({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<RegisterDesktop> createState() => _RegisterDesktopState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RegisterDesktopState extends State<RegisterDesktop> with RequestToolMixin {
|
||||||
|
late final TextEditingController _userNameController;
|
||||||
|
late final TextEditingController _passwordController;
|
||||||
|
late final TextEditingController _confirmPasswordController;
|
||||||
|
|
||||||
|
bool readAgreement = false;
|
||||||
|
bool _isShowPwd = true;
|
||||||
|
bool _isShowConfirmPwd = true;
|
||||||
|
bool canRegister = true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_userNameController = TextEditingController();
|
||||||
|
_passwordController = TextEditingController();
|
||||||
|
_confirmPasswordController = TextEditingController();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
_userNameController.dispose();
|
||||||
|
_passwordController.dispose();
|
||||||
|
_confirmPasswordController.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void toRegister() async {
|
||||||
|
if (!canRegister) return;
|
||||||
|
setState(() => canRegister = false);
|
||||||
|
void toMsg(msg) {
|
||||||
|
Future.delayed(Duration.zero, () => ToastUtils.showError(msg));
|
||||||
|
setState(() => canRegister = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String userName = _userNameController.text.trim();
|
||||||
|
String userPwd = _passwordController.text.trim();
|
||||||
|
String confirmPwd = _confirmPasswordController.text.trim();
|
||||||
|
|
||||||
|
if (userName.isEmpty) return toMsg('请填写用户账号');
|
||||||
|
if (userPwd.isEmpty) return toMsg('请填写密码');
|
||||||
|
if (userPwd.length < 6) return toMsg('密码长度不得少于6位');
|
||||||
|
if (userPwd != confirmPwd) return toMsg('两次输入的密码不一致');
|
||||||
|
if (!readAgreement) return toMsg('请勾选我已阅读用户协议和隐私协议');
|
||||||
|
|
||||||
|
EasyLoading.show(status: '注册中...');
|
||||||
|
await getClient().toRegister(UserRegisterParams(account: userName, password: userPwd));
|
||||||
|
ToastUtils.showSuccess('注册成功,请登录');
|
||||||
|
Get.back();
|
||||||
|
} catch (e) {
|
||||||
|
setState(() => canRegister = true);
|
||||||
|
} finally {
|
||||||
|
EasyLoading.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: const Color(0xFFF0F2F5),
|
||||||
|
body: Center(
|
||||||
|
child: Container(
|
||||||
|
width: 400.w,
|
||||||
|
padding: EdgeInsets.all(32.r),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.1),
|
||||||
|
blurRadius: 20,
|
||||||
|
offset: const Offset(0, 10),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'创建您的账户',
|
||||||
|
style: TextStyle(fontSize: 24.sp, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
SizedBox(height: 24.h),
|
||||||
|
_buildTextField(controller: _userNameController, hintText: "请输入账号", prefixIcon: Icons.person_outline),
|
||||||
|
SizedBox(height: 20.h),
|
||||||
|
_buildPasswordField(
|
||||||
|
controller: _passwordController,
|
||||||
|
hintText: "请输入密码",
|
||||||
|
prefixIcon: Icons.lock_outline,
|
||||||
|
obscureText: _isShowPwd,
|
||||||
|
onToggleVisibility: () => setState(() => _isShowPwd = !_isShowPwd),
|
||||||
|
),
|
||||||
|
SizedBox(height: 20.h),
|
||||||
|
_buildPasswordField(
|
||||||
|
controller: _confirmPasswordController,
|
||||||
|
hintText: "请再次输入密码",
|
||||||
|
prefixIcon: Icons.lock_outline,
|
||||||
|
obscureText: _isShowConfirmPwd,
|
||||||
|
onToggleVisibility: () => setState(() => _isShowConfirmPwd = !_isShowConfirmPwd),
|
||||||
|
),
|
||||||
|
SizedBox(height: 20.h),
|
||||||
|
InkWell(
|
||||||
|
onTap: toRegister,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: canRegister ? const Color(0xFF8C68FF) : const Color(0xFFdddddd),
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8.r)),
|
||||||
|
),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
width: double.infinity,
|
||||||
|
height: 50.h,
|
||||||
|
child: quickText('注 册', size: 18.sp, color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 20.h),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Checkbox(
|
||||||
|
value: readAgreement,
|
||||||
|
onChanged: (value) => setState(() => readAgreement = value ?? false),
|
||||||
|
),
|
||||||
|
const Text('我已阅读并同意'),
|
||||||
|
InkWell(
|
||||||
|
onTap: () =>
|
||||||
|
Get.toNamed(Routes.agreementPage, arguments: {"type": AGREEMENT_KEY.USER_AGREEMENT.name}),
|
||||||
|
child: Text('《用户协议》', style: TextStyle(color: Theme.of(context).primaryColor)),
|
||||||
|
),
|
||||||
|
const Text('和'),
|
||||||
|
InkWell(
|
||||||
|
onTap: () =>
|
||||||
|
Get.toNamed(Routes.agreementPage, arguments: {"type": AGREEMENT_KEY.PRIVACY_GREEMENT.name}),
|
||||||
|
child: Text('《隐私协议》', style: TextStyle(color: Theme.of(context).primaryColor)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 20.h),
|
||||||
|
InkWell(
|
||||||
|
onTap: () => Get.back(),
|
||||||
|
child: Text('已有账户?返回登录', style: TextStyle(color: Theme.of(context).primaryColor)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTextField(
|
||||||
|
{required TextEditingController controller, required String hintText, required IconData prefixIcon}) {
|
||||||
|
return TextField(
|
||||||
|
controller: controller,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: hintText,
|
||||||
|
prefixIcon: Icon(prefixIcon),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.r), borderSide: const BorderSide(color: Colors.grey)),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.r), borderSide: BorderSide(color: Colors.grey.shade300)),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.r), borderSide: BorderSide(color: Theme.of(context).primaryColor)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildPasswordField(
|
||||||
|
{required TextEditingController controller,
|
||||||
|
required String hintText,
|
||||||
|
required IconData prefixIcon,
|
||||||
|
required bool obscureText,
|
||||||
|
required VoidCallback onToggleVisibility}) {
|
||||||
|
return TextField(
|
||||||
|
controller: controller,
|
||||||
|
obscureText: obscureText,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: hintText,
|
||||||
|
prefixIcon: Icon(prefixIcon),
|
||||||
|
suffixIcon: IconButton(
|
||||||
|
icon: Icon(obscureText ? Icons.visibility_off : Icons.visibility), onPressed: onToggleVisibility),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.r), borderSide: const BorderSide(color: Colors.grey)),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.r), borderSide: BorderSide(color: Colors.grey.shade300)),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.r), borderSide: BorderSide(color: Theme.of(context).primaryColor)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,292 @@
|
||||||
|
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:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/const_text.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/job/user_register_params.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/utils/toast_utils.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
||||||
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
|
||||||
|
/// 注册页面
|
||||||
|
class RegisterMobile extends StatefulWidget {
|
||||||
|
const RegisterMobile({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<RegisterMobile> createState() => _RegisterMobileState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RegisterMobileState extends State<RegisterMobile> with RequestToolMixin {
|
||||||
|
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) {
|
||||||
|
Future.delayed(Duration.zero, () => 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 (userPwd.length < 6) return toMsg('密码长度不得少于6位');
|
||||||
|
if (!readAgreement) return toMsg('请勾选我已阅读用户协议和隐私协议');
|
||||||
|
EasyLoading.show(status: 'loading...');
|
||||||
|
var resultData = await getClient().toRegister(UserRegisterParams(account: userName, password: userPwd));
|
||||||
|
print(resultData);
|
||||||
|
// if (resultData.success) return toMsg(resultData.message ?? '注册失败,请重试');
|
||||||
|
ToastUtils.showSuccess('注册成功,请登录');
|
||||||
|
// 跳转登录页
|
||||||
|
Future.delayed(Duration.zero, () => Get.back());
|
||||||
|
} catch (e) {
|
||||||
|
setState(() => canLogin = true);
|
||||||
|
} 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/register_bg.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/login_logo_icon.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: (_) => 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 ? Theme.of(context).primaryColor : Colors.grey,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: const Color.fromRGBO(76, 199, 147, 0.5),
|
||||||
|
offset: Offset(4.w, 6.h), //阴影y轴偏移量
|
||||||
|
blurRadius: 10, //阴影模糊程度
|
||||||
|
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: () {
|
||||||
|
Get.toNamed(Routes.agreementPage,
|
||||||
|
arguments: {"type": AGREEMENT_KEY.USER_AGREEMENT.name});
|
||||||
|
},
|
||||||
|
child: quickText(
|
||||||
|
'《用户协议》',
|
||||||
|
size: 12.sp,
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.agreementPage,
|
||||||
|
arguments: {"type": AGREEMENT_KEY.PRIVACY_GREEMENT.name});
|
||||||
|
},
|
||||||
|
child: quickText(
|
||||||
|
'《隐私协议》',
|
||||||
|
size: 12.sp,
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
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),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,231 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/const_text.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/utils/anti_shake_throttling.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/utils/app_upgrade/upgradeLogic.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/utils/utils.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
||||||
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
|
||||||
|
import 'children/sys_protocol.dart';
|
||||||
|
import 'login_logic.dart';
|
||||||
|
|
||||||
|
class LoginDesktopPage extends StatefulWidget {
|
||||||
|
const LoginDesktopPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<LoginDesktopPage> createState() => _LoginDesktopPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _LoginDesktopPageState extends State<LoginDesktopPage> {
|
||||||
|
final logic = Get.find<LoginLogic>();
|
||||||
|
final upgradeLogic = Get.find<UpgradeLogic>();
|
||||||
|
final state = Get.find<LoginLogic>().state;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
|
||||||
|
statusBarIconBrightness: Brightness.dark,
|
||||||
|
statusBarColor: Colors.transparent, //状态栏背景颜色
|
||||||
|
));
|
||||||
|
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
|
await sysProtocol(context);
|
||||||
|
});
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
behavior: HitTestBehavior.translucent,
|
||||||
|
onTap: () {
|
||||||
|
Utils.hideKeyboard();
|
||||||
|
},
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: const Color(0xFFF0F2F5),
|
||||||
|
body: Center(
|
||||||
|
child: Container(
|
||||||
|
width: 400.w,
|
||||||
|
padding: EdgeInsets.all(32.r),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.1),
|
||||||
|
blurRadius: 20,
|
||||||
|
offset: const Offset(0, 10),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Image.asset('assets/images/login_logo_icon.png', height: 64.r),
|
||||||
|
SizedBox(height: 24.h),
|
||||||
|
Text(
|
||||||
|
'欢迎登录',
|
||||||
|
style: TextStyle(fontSize: 24.sp, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
SizedBox(height: 24.h),
|
||||||
|
_buildTextField(
|
||||||
|
controller: state.userNameController,
|
||||||
|
hintText: "请输入账号",
|
||||||
|
prefixIcon: Icons.person_outline,
|
||||||
|
),
|
||||||
|
SizedBox(height: 20.h),
|
||||||
|
Obx(
|
||||||
|
() => _buildPasswordField(
|
||||||
|
controller: state.passwordController,
|
||||||
|
hintText: "请输入密码",
|
||||||
|
prefixIcon: Icons.lock_outline,
|
||||||
|
obscureText: state.isShowPwd.value,
|
||||||
|
onToggleVisibility: () {
|
||||||
|
state.isShowPwd.value = !state.isShowPwd.value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 20.h),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Obx(() => Checkbox(
|
||||||
|
value: state.keepPwd.value,
|
||||||
|
onChanged: (value) {
|
||||||
|
state.keepPwd.value = value ?? false;
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
const Text('记住密码'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () => Get.toNamed(Routes.register),
|
||||||
|
child: Text('账号注册', style: TextStyle(color: Theme.of(context).primaryColor)),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 20.h),
|
||||||
|
InkWell(
|
||||||
|
onTap: () => easyThrottle('LOGIN_EASYTHROTTLE', () async {
|
||||||
|
Utils.hideKeyboard();
|
||||||
|
await Future.delayed(Duration.zero);
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) => logic.toLogin(context, upgradeLogic));
|
||||||
|
}),
|
||||||
|
child: Obx(() {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: state.canLogin.value ? const Color(0xFF8C68FF) : const Color(0xFFdddddd),
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(8.r),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
width: double.infinity,
|
||||||
|
height: 50.h,
|
||||||
|
child: quickText('登 录', size: 18.sp, color: Colors.white));
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
SizedBox(height: 20.h),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Obx(() => Checkbox(
|
||||||
|
value: state.readAgreement.value,
|
||||||
|
onChanged: (value) {
|
||||||
|
state.readAgreement.value = value ?? false;
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
const Text('我已阅读并同意'),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.agreementPage, arguments: {"type": AGREEMENT_KEY.USER_AGREEMENT.name});
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
'《用户协议》',
|
||||||
|
style: TextStyle(color: Theme.of(context).primaryColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Text('和'),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.agreementPage, arguments: {"type": AGREEMENT_KEY.PRIVACY_GREEMENT.name});
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
'《隐私协议》',
|
||||||
|
style: TextStyle(color: Theme.of(context).primaryColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTextField({
|
||||||
|
required TextEditingController controller,
|
||||||
|
required String hintText,
|
||||||
|
required IconData prefixIcon,
|
||||||
|
}) {
|
||||||
|
return TextField(
|
||||||
|
controller: controller,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: hintText,
|
||||||
|
prefixIcon: Icon(prefixIcon),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
borderSide: const BorderSide(color: Colors.grey),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
borderSide: BorderSide(color: Colors.grey.shade300),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
borderSide: BorderSide(color: Theme.of(context).primaryColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildPasswordField({
|
||||||
|
required TextEditingController controller,
|
||||||
|
required String hintText,
|
||||||
|
required IconData prefixIcon,
|
||||||
|
required bool obscureText,
|
||||||
|
required VoidCallback onToggleVisibility,
|
||||||
|
}) {
|
||||||
|
return TextField(
|
||||||
|
controller: controller,
|
||||||
|
obscureText: obscureText,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: hintText,
|
||||||
|
prefixIcon: Icon(prefixIcon),
|
||||||
|
suffixIcon: IconButton(
|
||||||
|
icon: Icon(obscureText ? Icons.visibility_off : Icons.visibility),
|
||||||
|
onPressed: onToggleVisibility,
|
||||||
|
),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
borderSide: const BorderSide(color: Colors.grey),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
borderSide: BorderSide(color: Colors.grey.shade300),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
borderSide: BorderSide(color: Theme.of(context).primaryColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,404 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/const_text.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/utils/anti_shake_throttling.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/utils/app_upgrade/upgradeLogic.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/utils/utils.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
||||||
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
|
||||||
|
import 'children/sys_protocol.dart';
|
||||||
|
import 'login_logic.dart';
|
||||||
|
|
||||||
|
class LoginMobilePage extends StatefulWidget {
|
||||||
|
const LoginMobilePage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<LoginMobilePage> createState() => _LoginMobilePageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _LoginMobilePageState extends State<LoginMobilePage> {
|
||||||
|
final logic = Get.find<LoginLogic>();
|
||||||
|
final upgradeLogic = Get.find<UpgradeLogic>();
|
||||||
|
final state = Get.find<LoginLogic>().state;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
|
||||||
|
statusBarIconBrightness: Brightness.light,
|
||||||
|
statusBarColor: Colors.transparent, //状态栏背景颜色
|
||||||
|
));
|
||||||
|
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
|
await sysProtocol(context);
|
||||||
|
|
||||||
|
/// 为了发布各平台方便审核 不能再登陆页面直接弹出审核
|
||||||
|
// await Future.delayed(Duration.zero, () => upgradeLogic.getAppUpgrade(context));
|
||||||
|
});
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
behavior: HitTestBehavior.translucent,
|
||||||
|
onTap: () {
|
||||||
|
Utils.hideKeyboard();
|
||||||
|
// FocusScope.of(context).requestFocus(state.theFocus);
|
||||||
|
},
|
||||||
|
child: AnnotatedRegion(
|
||||||
|
value: const SystemUiOverlayStyle(
|
||||||
|
statusBarColor: Colors.transparent,
|
||||||
|
systemNavigationBarIconBrightness: Brightness.light,
|
||||||
|
statusBarIconBrightness: Brightness.light,
|
||||||
|
statusBarBrightness: Brightness.dark,
|
||||||
|
),
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
resizeToAvoidBottomInset: false,
|
||||||
|
body: Stack(
|
||||||
|
children: [
|
||||||
|
Positioned(
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
child: Image.asset(
|
||||||
|
'assets/images/logo_banner.png',
|
||||||
|
width: Get.width,
|
||||||
|
fit: BoxFit.fill,
|
||||||
|
)),
|
||||||
|
SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: 130.r,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: 77.w,
|
||||||
|
height: 77.w,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 77.w,
|
||||||
|
width: 77.w,
|
||||||
|
child: Image.asset('assets/images/login_logo_icon.png', fit: BoxFit.cover),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
margin: EdgeInsets.only(top: 90.r),
|
||||||
|
padding: EdgeInsets.only(top: 50.h, bottom: 16.h, left: 40.w, right: 40.w),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.only(topLeft: Radius.circular(30.r), topRight: Radius.circular(30.r)),
|
||||||
|
/*boxShadow: const [
|
||||||
|
BoxShadow(
|
||||||
|
color: Color.fromRGBO(46, 91, 255, 0.1),
|
||||||
|
offset: Offset.zero, //阴影y轴偏移量
|
||||||
|
blurRadius: 100, //阴影模糊程度
|
||||||
|
spreadRadius: 100, //阴影扩散程度
|
||||||
|
)
|
||||||
|
],*/
|
||||||
|
),
|
||||||
|
child: Column(children: [
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 15.w,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.transparent,
|
||||||
|
border: Border.all(width: 1.w, color: const Color(0xFF434343)),
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(17.w)),
|
||||||
|
),
|
||||||
|
child: TextField(
|
||||||
|
controller: state.userNameController,
|
||||||
|
/* maxLines: 1,
|
||||||
|
maxLength: 20,*/
|
||||||
|
textInputAction: TextInputAction.next,
|
||||||
|
onEditingComplete: () {
|
||||||
|
Get.focusScope?.nextFocus();
|
||||||
|
// FocusScope.of(context).requestFocus(_pwdFocus);
|
||||||
|
},
|
||||||
|
style: TextStyle(
|
||||||
|
color: const Color(0xFF434343),
|
||||||
|
fontSize: 14.sp,
|
||||||
|
),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: "请输入账号",
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
color: const Color(0xFF434343),
|
||||||
|
),
|
||||||
|
// labelText: "账号",
|
||||||
|
labelStyle: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
color: const Color(0xFF434343),
|
||||||
|
),
|
||||||
|
border: InputBorder.none,
|
||||||
|
isDense: true,
|
||||||
|
prefixIconConstraints: BoxConstraints(
|
||||||
|
minHeight: 10.w,
|
||||||
|
minWidth: 10.h,
|
||||||
|
),
|
||||||
|
prefixIcon: Padding(
|
||||||
|
padding: EdgeInsets.only(right: 5.r),
|
||||||
|
child: Image.asset(
|
||||||
|
'assets/images/login_account.png',
|
||||||
|
width: 15.r,
|
||||||
|
height: 15.r,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 20.r,
|
||||||
|
),
|
||||||
|
Obx(() {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 15.w),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.transparent,
|
||||||
|
border: Border.all(width: 1.w, color: const Color(0xFF434343)),
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(17.w)),
|
||||||
|
),
|
||||||
|
child: TextField(
|
||||||
|
focusNode: state.pwdFocus,
|
||||||
|
controller: state.passwordController,
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
maxLines: 1,
|
||||||
|
obscureText: state.isShowPwd.value,
|
||||||
|
//隐藏密码显示
|
||||||
|
// textInputAction: state.isShowPwd.value?TextInputAction.go:TextInputAction.next,
|
||||||
|
textInputAction: TextInputAction.send,
|
||||||
|
onSubmitted: (_) => easyThrottle('LOGIN_EASYTHROTTLE', () async {
|
||||||
|
Utils.hideKeyboard();
|
||||||
|
await Future.delayed(const Duration(milliseconds: 300));
|
||||||
|
WidgetsBinding.instance
|
||||||
|
.addPostFrameCallback((_) => logic.toLogin(context, upgradeLogic));
|
||||||
|
}),
|
||||||
|
style: TextStyle(
|
||||||
|
color: const Color(0xFF434343),
|
||||||
|
fontSize: 14.sp,
|
||||||
|
),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: "请输入密码",
|
||||||
|
prefixIconConstraints: BoxConstraints(
|
||||||
|
minHeight: 10.w,
|
||||||
|
minWidth: 10.h,
|
||||||
|
),
|
||||||
|
prefixIcon: Padding(
|
||||||
|
padding: EdgeInsets.only(right: 5.r),
|
||||||
|
child: Image.asset(
|
||||||
|
'assets/images/login_pwd.png',
|
||||||
|
width: 15.r,
|
||||||
|
height: 15.r,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
suffixIconConstraints: BoxConstraints(
|
||||||
|
minHeight: 10.w,
|
||||||
|
minWidth: 10.h,
|
||||||
|
),
|
||||||
|
suffixIcon: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
state.isShowPwd.value = !state.isShowPwd.value;
|
||||||
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(right: 5.r),
|
||||||
|
child: Image.asset(
|
||||||
|
state.isShowPwd.value
|
||||||
|
? 'assets/images/eye_default.png'
|
||||||
|
: 'assets/images/eye_active.png',
|
||||||
|
width: 15.r,
|
||||||
|
height: 15.r,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
color: const Color(0xFF434343),
|
||||||
|
),
|
||||||
|
border: InputBorder.none,
|
||||||
|
// labelText: "密码",
|
||||||
|
isDense: true,
|
||||||
|
labelStyle: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
SizedBox(height: 10.h),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 25.w,
|
||||||
|
padding: EdgeInsets.only(right: 0.w),
|
||||||
|
child: Obx(() {
|
||||||
|
return Transform.scale(
|
||||||
|
scale: 1.0,
|
||||||
|
child: Checkbox(
|
||||||
|
// activeColor: Colors.transparent, //去掉勾选时背景颜色
|
||||||
|
|
||||||
|
activeColor: Theme.of(context).primaryColor,
|
||||||
|
// checkColor: Colors.white,
|
||||||
|
value: state.keepPwd.value,
|
||||||
|
onChanged: (value) {
|
||||||
|
// Get.focusScope?.nextFocus();
|
||||||
|
FocusScope.of(context).requestFocus(state.pwdFocus);
|
||||||
|
FocusScope.of(context).requestFocus(state.theFocus);
|
||||||
|
state.keepPwd.value = value ?? false;
|
||||||
|
},
|
||||||
|
side: WidgetStateBorderSide.resolveWith(
|
||||||
|
(Set<WidgetState> states) {
|
||||||
|
if (states.contains(WidgetState.selected)) {
|
||||||
|
//修改勾选时边框颜色为红色
|
||||||
|
return BorderSide(
|
||||||
|
width: 1.5.r, color: Theme.of(context).primaryColor);
|
||||||
|
}
|
||||||
|
//修改默认时边框颜色为绿色
|
||||||
|
return BorderSide(width: 1.r, color: const Color(0xFF434343));
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Utils.hideKeyboard();
|
||||||
|
Get.focusScope?.nextFocus();
|
||||||
|
Get.focusScope?.nextFocus();
|
||||||
|
FocusScope.of(context).requestFocus(state.pwdFocus);
|
||||||
|
FocusScope.of(context).requestFocus(state.theFocus);
|
||||||
|
state.keepPwd.value = !state.keepPwd.value;
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
'记住密码',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12.sp,
|
||||||
|
color: const Color(0xFF434343),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () => Get.toNamed(Routes.register),
|
||||||
|
child: quickText('账号注册', color: const Color(0xFF434343)),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () => easyThrottle('LOGIN_EASYTHROTTLE', () async {
|
||||||
|
Utils.hideKeyboard();
|
||||||
|
await Future.delayed(Duration.zero);
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) => logic.toLogin(context, upgradeLogic));
|
||||||
|
}),
|
||||||
|
child: Obx(() {
|
||||||
|
return Container(
|
||||||
|
margin: EdgeInsets.symmetric(vertical: 10.h),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: state.canLogin.value ? const Color(0xFF8C68FF) : const Color(0xFFdddddd),
|
||||||
|
/*boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color:
|
||||||
|
const Color.fromRGBO(76, 199, 147, 0.5),
|
||||||
|
offset: Offset(6.w, 10.h), //阴影y轴偏移量
|
||||||
|
blurRadius: 14, //阴影模糊程度
|
||||||
|
spreadRadius: 0.5, //阴影扩散程度
|
||||||
|
)
|
||||||
|
],*/
|
||||||
|
borderRadius: BorderRadius.all(
|
||||||
|
Radius.circular(17.w),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
width: double.infinity,
|
||||||
|
height: 50.h,
|
||||||
|
child: quickText('登 录', size: 18.sp, color: Colors.white));
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 25.w,
|
||||||
|
padding: EdgeInsets.only(right: 0.w),
|
||||||
|
child: Obx(() {
|
||||||
|
return Transform.scale(
|
||||||
|
scale: 1.0,
|
||||||
|
child: Checkbox(
|
||||||
|
activeColor: Theme.of(context).primaryColor,
|
||||||
|
checkColor: Colors.white,
|
||||||
|
value: state.readAgreement.value,
|
||||||
|
onChanged: (value) {
|
||||||
|
Utils.hideKeyboard();
|
||||||
|
/* FocusScope.of(context).requestFocus(
|
||||||
|
state.pwdFocus);
|
||||||
|
FocusScope.of(context).requestFocus(
|
||||||
|
state.theFocus);*/
|
||||||
|
state.readAgreement.value = value ?? false;
|
||||||
|
},
|
||||||
|
side: WidgetStateBorderSide.resolveWith(
|
||||||
|
(Set<WidgetState> states) {
|
||||||
|
if (states.contains(WidgetState.selected)) {
|
||||||
|
//修改勾选时边框颜色为红色
|
||||||
|
return BorderSide(width: 1.5.r, color: Theme.of(context).primaryColor);
|
||||||
|
}
|
||||||
|
//修改默认时边框颜色为绿色
|
||||||
|
return BorderSide(width: 1.r, color: const Color(0xFF434343));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.agreementPage,
|
||||||
|
arguments: {"type": AGREEMENT_KEY.USER_AGREEMENT.name});
|
||||||
|
},
|
||||||
|
child: quickText(
|
||||||
|
'请仔细阅读',
|
||||||
|
size: 11.sp,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.agreementPage,
|
||||||
|
arguments: {"type": AGREEMENT_KEY.USER_AGREEMENT.name});
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
'《用户协议》',
|
||||||
|
style: TextStyle(fontSize: 12.r, color: Theme.of(context).primaryColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.agreementPage,
|
||||||
|
arguments: {"type": AGREEMENT_KEY.PRIVACY_GREEMENT.name});
|
||||||
|
},
|
||||||
|
child: quickText(
|
||||||
|
'《隐私协议》',
|
||||||
|
size: 12.sp,
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,395 +1,13 @@
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:making_school_asignment_app/common/utils/platform_utils.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:making_school_asignment_app/page/login_page/login_desktop_view.dart';
|
||||||
import 'package:making_school_asignment_app/common/const_text.dart';
|
import 'package:making_school_asignment_app/page/login_page/login_mobile_view.dart';
|
||||||
import 'package:making_school_asignment_app/common/utils/anti_shake_throttling.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/utils/app_upgrade/upgradeLogic.dart';
|
|
||||||
import 'package:making_school_asignment_app/common/utils/utils.dart';
|
|
||||||
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
|
||||||
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
|
||||||
|
|
||||||
import 'children/sys_protocol.dart';
|
class LoginPage extends StatelessWidget {
|
||||||
import 'login_logic.dart';
|
|
||||||
|
|
||||||
class LoginPage extends StatefulWidget {
|
|
||||||
const LoginPage({super.key});
|
const LoginPage({super.key});
|
||||||
|
|
||||||
@override
|
|
||||||
State<LoginPage> createState() => _LoginPageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _LoginPageState extends State<LoginPage> {
|
|
||||||
final logic = Get.find<LoginLogic>();
|
|
||||||
final upgradeLogic = Get.find<UpgradeLogic>();
|
|
||||||
final state = Get.find<LoginLogic>().state;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
|
|
||||||
statusBarIconBrightness: Brightness.light,
|
|
||||||
statusBarColor: Colors.transparent, //状态栏背景颜色
|
|
||||||
));
|
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
|
||||||
await sysProtocol(context);
|
|
||||||
/// 为了发布各平台方便审核 不能再登陆页面直接弹出审核
|
|
||||||
// await Future.delayed(Duration.zero, () => upgradeLogic.getAppUpgrade(context));
|
|
||||||
});
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return PlatformUtils.isDesktop ? const LoginDesktopPage() : const LoginMobilePage();
|
||||||
behavior: HitTestBehavior.translucent,
|
|
||||||
onTap: () {
|
|
||||||
Utils.hideKeyboard();
|
|
||||||
// FocusScope.of(context).requestFocus(state.theFocus);
|
|
||||||
},
|
|
||||||
child: AnnotatedRegion(
|
|
||||||
value: const SystemUiOverlayStyle(
|
|
||||||
statusBarColor: Colors.transparent,
|
|
||||||
systemNavigationBarIconBrightness: Brightness.light,
|
|
||||||
statusBarIconBrightness: Brightness.light,
|
|
||||||
statusBarBrightness: Brightness.dark,
|
|
||||||
),
|
|
||||||
child: Scaffold(
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
resizeToAvoidBottomInset: false,
|
|
||||||
body: Stack(
|
|
||||||
children: [
|
|
||||||
Positioned(
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
child: Image.asset(
|
|
||||||
'assets/images/logo_banner.png',
|
|
||||||
width: Get.width,
|
|
||||||
fit: BoxFit.fill,
|
|
||||||
)),
|
|
||||||
SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
height: 130.r,
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
width: 77.w,
|
|
||||||
height: 77.w,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: SizedBox(
|
|
||||||
height: 77.w,
|
|
||||||
width: 77.w,
|
|
||||||
child: Image.asset('assets/images/login_logo_icon.png', fit: BoxFit.cover),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
margin: EdgeInsets.only(top: 90.r),
|
|
||||||
padding: EdgeInsets.only(top: 50.h, bottom: 16.h, left: 40.w, right: 40.w),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white,
|
|
||||||
borderRadius: BorderRadius.only(topLeft: Radius.circular(30.r), topRight: Radius.circular(30.r)),
|
|
||||||
/*boxShadow: const [
|
|
||||||
BoxShadow(
|
|
||||||
color: Color.fromRGBO(46, 91, 255, 0.1),
|
|
||||||
offset: Offset.zero, //阴影y轴偏移量
|
|
||||||
blurRadius: 100, //阴影模糊程度
|
|
||||||
spreadRadius: 100, //阴影扩散程度
|
|
||||||
)
|
|
||||||
],*/
|
|
||||||
),
|
|
||||||
child: Column(children: [
|
|
||||||
Container(
|
|
||||||
padding: EdgeInsets.symmetric(
|
|
||||||
horizontal: 15.w,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.transparent,
|
|
||||||
border: Border.all(width: 1.w, color: const Color(0xFF434343)),
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(17.w)),
|
|
||||||
),
|
|
||||||
child: TextField(
|
|
||||||
controller: state.userNameController,
|
|
||||||
/* maxLines: 1,
|
|
||||||
maxLength: 20,*/
|
|
||||||
textInputAction: TextInputAction.next,
|
|
||||||
onEditingComplete: () {
|
|
||||||
Get.focusScope?.nextFocus();
|
|
||||||
// FocusScope.of(context).requestFocus(_pwdFocus);
|
|
||||||
},
|
|
||||||
style: TextStyle(
|
|
||||||
color: const Color(0xFF434343),
|
|
||||||
fontSize: 14.sp,
|
|
||||||
),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
hintText: "请输入账号",
|
|
||||||
hintStyle: TextStyle(
|
|
||||||
fontSize: 14.sp,
|
|
||||||
color: const Color(0xFF434343),
|
|
||||||
),
|
|
||||||
// labelText: "账号",
|
|
||||||
labelStyle: TextStyle(
|
|
||||||
fontSize: 14.sp,
|
|
||||||
color: const Color(0xFF434343),
|
|
||||||
),
|
|
||||||
border: InputBorder.none,
|
|
||||||
isDense: true,
|
|
||||||
prefixIconConstraints: BoxConstraints(
|
|
||||||
minHeight: 10.w,
|
|
||||||
minWidth: 10.h,
|
|
||||||
),
|
|
||||||
prefixIcon: Padding(
|
|
||||||
padding: EdgeInsets.only(right: 5.r),
|
|
||||||
child: Image.asset(
|
|
||||||
'assets/images/login_account.png',
|
|
||||||
width: 15.r,
|
|
||||||
height: 15.r,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 20.r,
|
|
||||||
),
|
|
||||||
Obx(() {
|
|
||||||
return Container(
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 15.w),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.transparent,
|
|
||||||
border: Border.all(width: 1.w, color: const Color(0xFF434343)),
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(17.w)),
|
|
||||||
),
|
|
||||||
child: TextField(
|
|
||||||
focusNode: state.pwdFocus,
|
|
||||||
controller: state.passwordController,
|
|
||||||
keyboardType: TextInputType.number,
|
|
||||||
maxLines: 1,
|
|
||||||
obscureText: state.isShowPwd.value,
|
|
||||||
//隐藏密码显示
|
|
||||||
// textInputAction: state.isShowPwd.value?TextInputAction.go:TextInputAction.next,
|
|
||||||
textInputAction: TextInputAction.send,
|
|
||||||
onSubmitted: (_) => easyThrottle('LOGIN_EASYTHROTTLE', () async{
|
|
||||||
Utils.hideKeyboard();
|
|
||||||
await Future.delayed(const Duration(milliseconds: 300));
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) => logic.toLogin(context,upgradeLogic));
|
|
||||||
}),
|
|
||||||
style: TextStyle(
|
|
||||||
color: const Color(0xFF434343),
|
|
||||||
fontSize: 14.sp,
|
|
||||||
),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
hintText: "请输入密码",
|
|
||||||
prefixIconConstraints: BoxConstraints(
|
|
||||||
minHeight: 10.w,
|
|
||||||
minWidth: 10.h,
|
|
||||||
),
|
|
||||||
prefixIcon: Padding(
|
|
||||||
padding: EdgeInsets.only(right: 5.r),
|
|
||||||
child: Image.asset(
|
|
||||||
'assets/images/login_pwd.png',
|
|
||||||
width: 15.r,
|
|
||||||
height: 15.r,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
suffixIconConstraints: BoxConstraints(
|
|
||||||
minHeight: 10.w,
|
|
||||||
minWidth: 10.h,
|
|
||||||
),
|
|
||||||
suffixIcon: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
state.isShowPwd.value = !state.isShowPwd.value;
|
|
||||||
},
|
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.only(right: 5.r),
|
|
||||||
child: Image.asset(
|
|
||||||
state.isShowPwd.value ? 'assets/images/eye_default.png' : 'assets/images/eye_active.png',
|
|
||||||
width: 15.r,
|
|
||||||
height: 15.r,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
hintStyle: TextStyle(
|
|
||||||
fontSize: 14.sp,
|
|
||||||
color: const Color(0xFF434343),
|
|
||||||
),
|
|
||||||
border: InputBorder.none,
|
|
||||||
// labelText: "密码",
|
|
||||||
isDense: true,
|
|
||||||
labelStyle: TextStyle(
|
|
||||||
fontSize: 14.sp,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
SizedBox(height: 10.h),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
width: 25.w,
|
|
||||||
padding: EdgeInsets.only(right: 0.w),
|
|
||||||
child: Obx(() {
|
|
||||||
return Transform.scale(
|
|
||||||
scale: 1.0,
|
|
||||||
child: Checkbox(
|
|
||||||
// activeColor: Colors.transparent, //去掉勾选时背景颜色
|
|
||||||
|
|
||||||
activeColor: Theme.of(context).primaryColor,
|
|
||||||
// checkColor: Colors.white,
|
|
||||||
value: state.keepPwd.value,
|
|
||||||
onChanged: (value) {
|
|
||||||
// Get.focusScope?.nextFocus();
|
|
||||||
FocusScope.of(context).requestFocus(state.pwdFocus);
|
|
||||||
FocusScope.of(context).requestFocus(state.theFocus);
|
|
||||||
state.keepPwd.value = value ?? false;
|
|
||||||
},
|
|
||||||
side: WidgetStateBorderSide.resolveWith(
|
|
||||||
(Set<WidgetState> states) {
|
|
||||||
if (states.contains(WidgetState.selected)) {
|
|
||||||
//修改勾选时边框颜色为红色
|
|
||||||
return BorderSide(width: 1.5.r, color: Theme.of(context).primaryColor);
|
|
||||||
}
|
|
||||||
//修改默认时边框颜色为绿色
|
|
||||||
return BorderSide(width: 1.r, color: const Color(0xFF434343));
|
|
||||||
},
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
Utils.hideKeyboard();
|
|
||||||
Get.focusScope?.nextFocus();
|
|
||||||
Get.focusScope?.nextFocus();
|
|
||||||
FocusScope.of(context).requestFocus(state.pwdFocus);
|
|
||||||
FocusScope.of(context).requestFocus(state.theFocus);
|
|
||||||
state.keepPwd.value = !state.keepPwd.value;
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
'记住密码',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12.sp,
|
|
||||||
color: const Color(0xFF434343),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
onTap: () => Get.toNamed(Routes.register),
|
|
||||||
child: quickText('账号注册', color: const Color(0xFF434343)),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
onTap: () => easyThrottle('LOGIN_EASYTHROTTLE', () async{
|
|
||||||
Utils.hideKeyboard();
|
|
||||||
await Future.delayed(Duration.zero);
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) => logic.toLogin(context,upgradeLogic));
|
|
||||||
}),
|
|
||||||
child: Obx(() {
|
|
||||||
return Container(
|
|
||||||
margin: EdgeInsets.symmetric(vertical: 10.h),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: state.canLogin.value ? const Color(0xFF8C68FF) : const Color(0xFFdddddd),
|
|
||||||
/*boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color:
|
|
||||||
const Color.fromRGBO(76, 199, 147, 0.5),
|
|
||||||
offset: Offset(6.w, 10.h), //阴影y轴偏移量
|
|
||||||
blurRadius: 14, //阴影模糊程度
|
|
||||||
spreadRadius: 0.5, //阴影扩散程度
|
|
||||||
)
|
|
||||||
],*/
|
|
||||||
borderRadius: BorderRadius.all(
|
|
||||||
Radius.circular(17.w),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
width: double.infinity,
|
|
||||||
height: 50.h,
|
|
||||||
child: quickText('登 录', size: 18.sp, color: Colors.white));
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
width: 25.w,
|
|
||||||
padding: EdgeInsets.only(right: 0.w),
|
|
||||||
child: Obx(() {
|
|
||||||
return Transform.scale(
|
|
||||||
scale: 1.0,
|
|
||||||
child: Checkbox(
|
|
||||||
activeColor: Theme.of(context).primaryColor,
|
|
||||||
checkColor: Colors.white,
|
|
||||||
value: state.readAgreement.value,
|
|
||||||
onChanged: (value) {
|
|
||||||
Utils.hideKeyboard();
|
|
||||||
/* FocusScope.of(context).requestFocus(
|
|
||||||
state.pwdFocus);
|
|
||||||
FocusScope.of(context).requestFocus(
|
|
||||||
state.theFocus);*/
|
|
||||||
state.readAgreement.value = value ?? false;
|
|
||||||
},
|
|
||||||
side: WidgetStateBorderSide.resolveWith(
|
|
||||||
(Set<WidgetState> states) {
|
|
||||||
if (states.contains(WidgetState.selected)) {
|
|
||||||
//修改勾选时边框颜色为红色
|
|
||||||
return BorderSide(width: 1.5.r, color: Theme.of(context).primaryColor);
|
|
||||||
}
|
|
||||||
//修改默认时边框颜色为绿色
|
|
||||||
return BorderSide(width: 1.r, color: const Color(0xFF434343));
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
Get.toNamed(Routes.agreementPage, arguments: {"type": AGREEMENT_KEY.USER_AGREEMENT.name});
|
|
||||||
},
|
|
||||||
child: quickText(
|
|
||||||
'请仔细阅读',
|
|
||||||
size: 11.sp,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
Get.toNamed(Routes.agreementPage, arguments: {"type": AGREEMENT_KEY.USER_AGREEMENT.name});
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
'《用户协议》',
|
|
||||||
style: TextStyle(fontSize: 12.r, color: Theme.of(context).primaryColor),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
Get.toNamed(Routes.agreementPage, arguments: {"type": AGREEMENT_KEY.PRIVACY_GREEMENT.name});
|
|
||||||
},
|
|
||||||
child: quickText(
|
|
||||||
'《隐私协议》',
|
|
||||||
size: 12.sp,
|
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/mixins/getx_keepalive_widget.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/home_page/children/read_over/widget/annotate_list.dart';
|
||||||
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
|
||||||
|
import 'work_logic.dart';
|
||||||
|
|
||||||
|
class WorkDesktopPage extends GetxKeepAliveWidget<WorkLogic> {
|
||||||
|
const WorkDesktopPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget buildContent(BuildContext context, WorkLogic controller) {
|
||||||
|
final state = controller.state;
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: const Color(0xFFF0F2F5),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
_buildHeader(context, controller, state),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(24.r),
|
||||||
|
child: Card(
|
||||||
|
elevation: 2,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.r)),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
_buildTabBar(context, controller, state),
|
||||||
|
Expanded(
|
||||||
|
child: Obx(() {
|
||||||
|
return AnnotateList(
|
||||||
|
tabIndex: state.tabIndex.value,
|
||||||
|
assessType: 1,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildHeader(BuildContext context, WorkLogic controller, dynamic state) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.all(24.r),
|
||||||
|
color: Colors.white,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'作业批阅',
|
||||||
|
style: TextStyle(fontSize: 24.sp, fontWeight: FontWeight.bold, color: const Color(0xFF333333)),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
Get.toNamed(Routes.studentHistoryWorkPage, arguments: {'page': 'set'});
|
||||||
|
},
|
||||||
|
icon: Icon(Icons.settings, size: 24.sp, color: Colors.grey[600]),
|
||||||
|
tooltip: '设置',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTabBar(BuildContext context, WorkLogic controller, dynamic state) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.all(16.r),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
height: 48.h,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.grey[100],
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
),
|
||||||
|
child: TabBar(
|
||||||
|
controller: controller.tabController,
|
||||||
|
indicator: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(6.r),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.1),
|
||||||
|
blurRadius: 4,
|
||||||
|
offset: const Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
indicatorPadding: EdgeInsets.all(4.r),
|
||||||
|
labelColor: Theme.of(context).primaryColor,
|
||||||
|
unselectedLabelColor: Colors.grey[600],
|
||||||
|
labelStyle: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.w600),
|
||||||
|
unselectedLabelStyle: TextStyle(fontSize: 14.sp),
|
||||||
|
onTap: (index) {
|
||||||
|
state.tabIndex.value = index;
|
||||||
|
if (index == 1 && state.completedToRefresh) {
|
||||||
|
state.completedToRefresh = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tabs: const [
|
||||||
|
Tab(text: '待批阅'),
|
||||||
|
Tab(text: '已批阅'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:making_school_asignment_app/common/mixins/getx_keepalive_widget.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
||||||
|
import 'package:making_school_asignment_app/page/home_page/children/read_over/widget/annotate_list.dart';
|
||||||
|
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
||||||
|
|
||||||
|
import 'work_logic.dart';
|
||||||
|
|
||||||
|
class WorkMobilePage extends GetxKeepAliveWidget<WorkLogic> {
|
||||||
|
const WorkMobilePage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget buildContent(BuildContext context, WorkLogic controller) {
|
||||||
|
final state = controller.state;
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: const Color.fromRGBO(244, 244, 244, 1),
|
||||||
|
body: Column(
|
||||||
|
children: <Widget>[
|
||||||
|
Container(
|
||||||
|
color: Colors.white,
|
||||||
|
margin: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
|
||||||
|
padding: EdgeInsets.only(bottom: 9.h, top: 4.h),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Container(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
padding: EdgeInsets.only(left: 10.w),
|
||||||
|
)),
|
||||||
|
Expanded(
|
||||||
|
flex: 4,
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 2.h),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color.fromRGBO(243, 243, 243, 1),
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
),
|
||||||
|
child: TabBar(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
indicatorPadding: EdgeInsets.zero,
|
||||||
|
indicatorWeight: 0,
|
||||||
|
labelPadding: EdgeInsets.symmetric(horizontal: 2.w),
|
||||||
|
controller: controller.tabController,
|
||||||
|
unselectedLabelStyle: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
color: const Color.fromRGBO(69, 83, 100, 1),
|
||||||
|
),
|
||||||
|
labelStyle: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
color: const Color(0xFF4CC793),
|
||||||
|
),
|
||||||
|
// labelColor: const Color.fromRGBO(45, 56, 76, 1),
|
||||||
|
indicator: const BoxDecoration(),
|
||||||
|
onTap: (index) {
|
||||||
|
state.tabIndex.value = index;
|
||||||
|
if (index == 1 && state.completedToRefresh) {
|
||||||
|
// 已阅卷
|
||||||
|
// _refreshController2.callRefresh();
|
||||||
|
state.completedToRefresh = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tabs: <Widget>[
|
||||||
|
Tab(
|
||||||
|
iconMargin: EdgeInsets.zero,
|
||||||
|
height: 34.h,
|
||||||
|
child: Obx(() {
|
||||||
|
return Container(
|
||||||
|
width: 140.w,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: state.tabIndex.value == 0 ? const Color.fromRGBO(255, 255, 255, 1) : null,
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8.r)),
|
||||||
|
),
|
||||||
|
child: quickText(
|
||||||
|
'待批阅',
|
||||||
|
size: 14.sp,
|
||||||
|
color: state.tabIndex.value == 0
|
||||||
|
? Theme.of(context).primaryColor
|
||||||
|
: const Color.fromRGBO(80, 94, 110, 1),
|
||||||
|
fontWeight: state.tabIndex.value == 0 ? FontWeight.bold : null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
iconMargin: EdgeInsets.zero,
|
||||||
|
height: 34.h,
|
||||||
|
child: Obx(() {
|
||||||
|
return Container(
|
||||||
|
width: 140.w,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: state.tabIndex.value == 1 ? const Color.fromRGBO(255, 255, 255, 1) : null,
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8.r)),
|
||||||
|
),
|
||||||
|
child: quickText(
|
||||||
|
'已批阅',
|
||||||
|
size: 14.sp,
|
||||||
|
color: state.tabIndex.value == 1
|
||||||
|
? Theme.of(context).primaryColor
|
||||||
|
: const Color.fromRGBO(80, 94, 110, 1),
|
||||||
|
fontWeight: state.tabIndex.value == 1 ? FontWeight.bold : null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.studentHistoryWorkPage, arguments: {'page': 'set'});
|
||||||
|
},
|
||||||
|
child: Icon(const IconData(0xe63e, fontFamily: "AlibabaIcon"),
|
||||||
|
color: const Color.fromRGBO(44, 48, 63, 1), size: 24.sp),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Obx(() {
|
||||||
|
return AnnotateList(
|
||||||
|
tabIndex: state.tabIndex.value,
|
||||||
|
assessType: 1,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,141 +1,13 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:making_school_asignment_app/common/utils/platform_utils.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:making_school_asignment_app/page/work_page/work_desktop_view.dart';
|
||||||
import 'package:making_school_asignment_app/common/mixins/getx_keepalive_widget.dart';
|
import 'package:making_school_asignment_app/page/work_page/work_mobile_view.dart';
|
||||||
import 'package:making_school_asignment_app/page/global_widget/my_text.dart';
|
|
||||||
import 'package:making_school_asignment_app/page/home_page/children/read_over/widget/annotate_list.dart';
|
|
||||||
import 'package:making_school_asignment_app/routes/app_pages.dart';
|
|
||||||
|
|
||||||
import 'work_logic.dart';
|
class WorkPage extends StatelessWidget {
|
||||||
|
|
||||||
class WorkPage extends GetxKeepAliveWidget<WorkLogic> {
|
|
||||||
const WorkPage({super.key});
|
const WorkPage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildContent(BuildContext context, WorkLogic controller) {
|
Widget build(BuildContext context) {
|
||||||
final state = controller.state;
|
return PlatformUtils.isDesktop ? const WorkDesktopPage() : const WorkMobilePage();
|
||||||
return Scaffold(
|
|
||||||
backgroundColor: const Color.fromRGBO(244, 244, 244, 1),
|
|
||||||
body: Column(
|
|
||||||
children: <Widget>[
|
|
||||||
Container(
|
|
||||||
color: Colors.white,
|
|
||||||
margin: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
|
|
||||||
padding: EdgeInsets.only(bottom: 9.h, top: 4.h),
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
flex: 1,
|
|
||||||
child: Container(
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
padding: EdgeInsets.only(left: 10.w),
|
|
||||||
)),
|
|
||||||
Expanded(
|
|
||||||
flex: 4,
|
|
||||||
child: Container(
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 2.h),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: const Color.fromRGBO(243, 243, 243, 1),
|
|
||||||
borderRadius: BorderRadius.circular(8.r),
|
|
||||||
),
|
|
||||||
child: TabBar(
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
indicatorPadding: EdgeInsets.zero,
|
|
||||||
indicatorWeight: 0,
|
|
||||||
labelPadding: EdgeInsets.symmetric(horizontal: 2.w),
|
|
||||||
controller: controller.tabController,
|
|
||||||
unselectedLabelStyle: TextStyle(
|
|
||||||
fontSize: 14.sp,
|
|
||||||
color: const Color.fromRGBO(69, 83, 100, 1),
|
|
||||||
),
|
|
||||||
labelStyle: TextStyle(
|
|
||||||
fontSize: 14.sp,
|
|
||||||
color: const Color(0xFF4CC793),
|
|
||||||
),
|
|
||||||
// labelColor: const Color.fromRGBO(45, 56, 76, 1),
|
|
||||||
indicator: const BoxDecoration(),
|
|
||||||
onTap: (index) {
|
|
||||||
state.tabIndex.value = index;
|
|
||||||
if (index == 1 && state.completedToRefresh) {
|
|
||||||
// 已阅卷
|
|
||||||
// _refreshController2.callRefresh();
|
|
||||||
state.completedToRefresh = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tabs: <Widget>[
|
|
||||||
Tab(
|
|
||||||
iconMargin: EdgeInsets.zero,
|
|
||||||
height: 34.h,
|
|
||||||
child: Obx(() {
|
|
||||||
return Container(
|
|
||||||
width: 140.w,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: state.tabIndex.value == 0 ? const Color.fromRGBO(255, 255, 255, 1) : null,
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(8.r)),
|
|
||||||
),
|
|
||||||
child: quickText(
|
|
||||||
'待批阅',
|
|
||||||
size: 14.sp,
|
|
||||||
color: state.tabIndex.value == 0
|
|
||||||
? Theme.of(context).primaryColor
|
|
||||||
: const Color.fromRGBO(80, 94, 110, 1),
|
|
||||||
fontWeight: state.tabIndex.value == 0 ? FontWeight.bold : null,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
Tab(
|
|
||||||
iconMargin: EdgeInsets.zero,
|
|
||||||
height: 34.h,
|
|
||||||
child: Obx(() {
|
|
||||||
return Container(
|
|
||||||
width: 140.w,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: state.tabIndex.value == 1 ? const Color.fromRGBO(255, 255, 255, 1) : null,
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(8.r)),
|
|
||||||
),
|
|
||||||
child: quickText(
|
|
||||||
'已批阅',
|
|
||||||
size: 14.sp,
|
|
||||||
color: state.tabIndex.value == 1
|
|
||||||
? Theme.of(context).primaryColor
|
|
||||||
: const Color.fromRGBO(80, 94, 110, 1),
|
|
||||||
fontWeight: state.tabIndex.value == 1 ? FontWeight.bold : null,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
flex: 1,
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
Get.toNamed(Routes.studentHistoryWorkPage, arguments: {'page': 'set'});
|
|
||||||
},
|
|
||||||
child: Icon(const IconData(0xe63e, fontFamily: "AlibabaIcon"),
|
|
||||||
color: const Color.fromRGBO(44, 48, 63, 1), size: 24.sp),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Obx(() {
|
|
||||||
return AnnotateList(
|
|
||||||
tabIndex: state.tabIndex.value,
|
|
||||||
assessType: 1,
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue