feat(apps): establish shared mobile design system

This commit is contained in:
2026-08-10 23:31:44 +08:00
parent 7242048abf
commit a2383fc8a1
34 changed files with 2007 additions and 751 deletions

View File

@@ -16,6 +16,7 @@ class _LoginPageState extends State<LoginPage> {
final _password = TextEditingController();
bool _busy = false;
String? _error;
bool _obscurePassword = true;
Future<void> _login() async {
setState(() {
@@ -43,28 +44,43 @@ class _LoginPageState extends State<LoginPage> {
body: SafeArea(
child: Center(
child: SingleChildScrollView(
padding: const EdgeInsets.all(24),
padding: const EdgeInsets.fromLTRB(24, 32, 24, 24),
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 420),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Icon(
Icons.engineering_rounded,
size: 72,
color: Theme.of(context).colorScheme.primary,
Align(
child: Container(
width: 72,
height: 72,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.primaryContainer,
borderRadius: BorderRadius.circular(24),
),
child: Icon(
Icons.engineering_rounded,
size: 38,
color: Theme.of(context).colorScheme.primary,
semanticLabel: '服务工作台标识',
),
),
),
const SizedBox(height: 20),
const SizedBox(height: 24),
Text(
'瓶安芯服务工作台',
textAlign: TextAlign.center,
style: Theme.of(
context,
).textTheme.headlineMedium?.copyWith(fontWeight: FontWeight.w900),
style: Theme.of(context).textTheme.headlineMedium,
),
const SizedBox(height: 8),
const Text('配送、安装维修与安检共用入口', textAlign: TextAlign.center),
const SizedBox(height: 34),
Text(
'配送、安装维修与安检共用入口',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: 40),
TextField(
controller: _phone,
keyboardType: TextInputType.phone,
@@ -76,22 +92,50 @@ class _LoginPageState extends State<LoginPage> {
const SizedBox(height: 14),
TextField(
controller: _password,
obscureText: true,
decoration: const InputDecoration(
obscureText: _obscurePassword,
autofillHints: const [AutofillHints.password],
decoration: InputDecoration(
labelText: '登录密码',
prefixIcon: Icon(Icons.lock_outline),
prefixIcon: const Icon(Icons.lock_outline),
suffixIcon: IconButton(
tooltip: _obscurePassword ? '显示密码' : '隐藏密码',
onPressed: () => setState(() => _obscurePassword = !_obscurePassword),
icon: Icon(
_obscurePassword
? Icons.visibility_outlined
: Icons.visibility_off_outlined,
),
),
),
),
if (_error != null)
Padding(
padding: const EdgeInsets.only(top: 12),
child: Text(
_error!,
style: TextStyle(color: Theme.of(context).colorScheme.error),
child: Semantics(
liveRegion: true,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(
Icons.error_outline,
size: 20,
color: Theme.of(context).colorScheme.error,
),
const SizedBox(width: 8),
Expanded(
child: Text(
_error!,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Theme.of(context).colorScheme.error,
),
),
),
],
),
),
),
const SizedBox(height: 20),
ElevatedButton(
const SizedBox(height: 24),
FilledButton(
onPressed: _busy ? null : _login,
child: _busy
? const SizedBox.square(
@@ -100,11 +144,13 @@ class _LoginPageState extends State<LoginPage> {
)
: const Text('进入工作台'),
),
const SizedBox(height: 12),
const Text(
const SizedBox(height: 16),
Text(
'账号与角色由平台审核分配,不提供自助注册',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 12),
style: Theme.of(context).textTheme.labelSmall?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
],
),