feat: add Flutter schema-driven form cards
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
import 'package:aioa_mobile/app/router.dart';
|
||||
import 'package:aioa_mobile/app/theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AioaApp extends StatelessWidget {
|
||||
const AioaApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp.router(
|
||||
title: 'AIOA',
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: buildAioaTheme(),
|
||||
routerConfig: appRouter,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import 'package:aioa_mobile/app/shell.dart';
|
||||
import 'package:aioa_mobile/features/assistant/presentation/assistant_page.dart';
|
||||
import 'package:aioa_mobile/features/form/presentation/leave_form_page.dart';
|
||||
import 'package:aioa_mobile/features/profile/presentation/profile_page.dart';
|
||||
import 'package:aioa_mobile/features/tasks/presentation/tasks_page.dart';
|
||||
import 'package:aioa_mobile/features/workspace/presentation/workspace_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
final appRouter = GoRouter(
|
||||
initialLocation: '/workspace',
|
||||
routes: [
|
||||
ShellRoute(
|
||||
builder: (context, state, child) =>
|
||||
AioaShell(location: state.uri.path, child: child),
|
||||
routes: [
|
||||
GoRoute(path: '/workspace', builder: (_, _) => const WorkspacePage()),
|
||||
GoRoute(path: '/assistant', builder: (_, _) => const AssistantPage()),
|
||||
GoRoute(path: '/tasks', builder: (_, _) => const TasksPage()),
|
||||
GoRoute(path: '/profile', builder: (_, _) => const ProfilePage()),
|
||||
],
|
||||
),
|
||||
GoRoute(
|
||||
path: '/leave/new',
|
||||
pageBuilder: (context, state) => MaterialPage<void>(
|
||||
fullscreenDialog: true,
|
||||
child: const LeaveFormPage(),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -0,0 +1,47 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
class AioaShell extends StatelessWidget {
|
||||
const AioaShell({super.key, required this.location, required this.child});
|
||||
|
||||
final String location;
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final index = switch (location) {
|
||||
String path when path.startsWith('/assistant') => 1,
|
||||
String path when path.startsWith('/tasks') => 2,
|
||||
String path when path.startsWith('/profile') => 3,
|
||||
_ => 0,
|
||||
};
|
||||
return Scaffold(
|
||||
body: SafeArea(child: child),
|
||||
bottomNavigationBar: NavigationBar(
|
||||
selectedIndex: index,
|
||||
onDestinationSelected: (value) {
|
||||
const paths = ['/workspace', '/assistant', '/tasks', '/profile'];
|
||||
context.go(paths[value]);
|
||||
},
|
||||
destinations: const [
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.grid_view_rounded),
|
||||
label: '工作台',
|
||||
),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.auto_awesome_rounded),
|
||||
label: 'AI 助手',
|
||||
),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.task_alt_rounded),
|
||||
label: '待办',
|
||||
),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.person_outline_rounded),
|
||||
label: '我的',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
ThemeData buildAioaTheme() {
|
||||
const seed = Color(0xFF3157D5);
|
||||
final scheme = ColorScheme.fromSeed(
|
||||
seedColor: seed,
|
||||
brightness: Brightness.light,
|
||||
surface: const Color(0xFFF7F8FC),
|
||||
);
|
||||
return ThemeData(
|
||||
colorScheme: scheme,
|
||||
useMaterial3: true,
|
||||
scaffoldBackgroundColor: scheme.surface,
|
||||
cardTheme: const CardThemeData(
|
||||
elevation: 0,
|
||||
margin: EdgeInsets.zero,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
side: BorderSide(color: Color(0xFFE6E8F0)),
|
||||
),
|
||||
),
|
||||
inputDecorationTheme: const InputDecorationTheme(
|
||||
filled: true,
|
||||
fillColor: Colors.white,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(14)),
|
||||
borderSide: BorderSide(color: Color(0xFFDDE1EA)),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(14)),
|
||||
borderSide: BorderSide(color: Color(0xFFDDE1EA)),
|
||||
),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 14),
|
||||
),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user