import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; import '../../app/app_controller.dart'; import '../../app/app_theme.dart'; import '../profile/import_preview.dart'; import 'school_session.dart'; class SchoolAuthPage extends StatefulWidget { const SchoolAuthPage({ super.key, required this.session, required this.controller, }); final SchoolSession session; final AppController controller; @override State createState() => _SchoolAuthPageState(); } class _SchoolAuthPageState extends State { final _username = TextEditingController(), _password = TextEditingController(); bool _showWeb = false, _previewing = false; @override void initState() { super.initState(); widget.session.addListener(_changed); if (!widget.session.hasOpened) { widget.session.open(); } } void _changed() { if (!mounted) return; setState(() {}); final draft = widget.session.pendingDraft; if (draft != null && !_previewing) { _previewing = true; WidgetsBinding.instance.addPostFrameCallback((_) async { if (!mounted) return; await showModalBottomSheet( context: context, isScrollControlled: true, showDragHandle: true, builder: (_) => ImportPreview(draft: draft, controller: widget.controller), ); widget.session.pendingDraft = null; _previewing = false; }); } } @override void dispose() { widget.session.removeListener(_changed); _password.clear(); _username.clear(); _password.dispose(); _username.dispose(); super.dispose(); } Future _submit() async { if (_username.text.trim().isEmpty || _password.text.isEmpty) { ScaffoldMessenger.of(context) .showSnackBar(const SnackBar(content: Text('请输入学号和密码'))); return; } try { await widget.session.submitCredentials( _username.text.trim(), _password.text, ); } finally { _password.clear(); if (mounted) { setState(() => _showWeb = true); } } } @override Widget build(BuildContext context) { final s = widget.session; return Scaffold( appBar: AppBar( title: const Text( '学校认证', style: TextStyle(fontSize: 20, fontWeight: FontWeight.w700), ), actions: [ IconButton( tooltip: _showWeb ? '应用登录界面' : '学校页面', onPressed: () => setState(() => _showWeb = !_showWeb), icon: Icon( _showWeb ? Icons.person_outline : Icons.language_rounded, ), ), IconButton( tooltip: '打开学校课表', onPressed: () { setState(() => _showWeb = true); s.openTimetable(); }, icon: const Icon(Icons.calendar_month_outlined), ), ], ), body: Column( children: [ if (s.busy) const LinearProgressIndicator(minHeight: 2), Container( width: double.infinity, padding: const EdgeInsets.all(13), color: river.withValues(alpha: 0.07), child: Text( s.message, style: const TextStyle(fontSize: 12, height: 1.5, color: ink), ), ), Expanded( child: _showWeb ? WebViewWidget(controller: s.web) : ListView( padding: const EdgeInsets.all(24), children: [ const SizedBox(height: 20), const Icon(Icons.school_outlined, size: 48, color: river), const SizedBox(height: 20), const Text( '登录,连接你的每一天。', textAlign: TextAlign.center, style: TextStyle( fontSize: 23, fontWeight: FontWeight.w700, ), ), const SizedBox(height: 10), Text( '电子科技大学统一身份认证', textAlign: TextAlign.center, style: TextStyle( fontSize: 13, color: ink.withValues(alpha: 0.5), ), ), const SizedBox(height: 30), SurfaceCard( child: Column( children: [ TextField( controller: _username, textInputAction: TextInputAction.next, autocorrect: false, decoration: const InputDecoration( labelText: '学号/工号', prefixIcon: Icon(Icons.person_outline), ), ), const SizedBox(height: 16), TextField( controller: _password, obscureText: true, enableSuggestions: false, autocorrect: false, decoration: const InputDecoration( labelText: '学校密码', prefixIcon: Icon(Icons.lock_outline), ), onSubmitted: (_) => _submit(), ), const SizedBox(height: 20), SizedBox( width: double.infinity, child: FilledButton( onPressed: !s.busy && s.formReady ? _submit : null, child: Text(s.busy ? '正在准备学校认证…' : '登录并打开课表'), ), ), const SizedBox(height: 10), TextButton( onPressed: () { _password.clear(); setState(() => _showWeb = true); s.openAuthentication(); }, child: const Text('使用学校页面登录'), ), ], ), ), const SizedBox(height: 20), Text( '密码仅交给学校处理,不在应用中保存。需要验证码或其他验证时,将由学校页面继续处理。', textAlign: TextAlign.center, style: TextStyle( fontSize: 12, height: 1.7, color: ink.withValues(alpha: 0.45), ), ), const SizedBox(height: 14), Text( '学校课表识别待登录后联调;也可通过「我的」导入课表文件。', textAlign: TextAlign.center, style: TextStyle( fontSize: 11, height: 1.6, color: ink.withValues(alpha: 0.45), ), ), ], ), ), ], ), ); } }