feat(client): 录单表单优化 + 可搜索下拉支持新建 + 日期选择器组件
新增 DatePickerField 日期选择器与 date_util;可搜索下拉 SearchableOptionField 支持内联新建选项;入库/出库录单表单、商品页、财务页、app_shell 导航相应调整。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -20,8 +20,7 @@ import '../../screens/about/about_screen.dart';
|
||||
import '../../screens/devices/device_management_screen.dart';
|
||||
import '../auth/auth_state.dart';
|
||||
|
||||
Page<void> _noTransition(Widget child) =>
|
||||
NoTransitionPage<void>(child: child);
|
||||
Page<void> _noTransition(Widget child) => NoTransitionPage<void>(child: child);
|
||||
|
||||
/// ChangeNotifier that bridges Riverpod auth state → GoRouter refreshListenable.
|
||||
class _RouterNotifier extends ChangeNotifier {
|
||||
@@ -94,74 +93,106 @@ final appRouterProvider = Provider<GoRouter>((ref) {
|
||||
path: '/login',
|
||||
builder: (context, state) => const LoginScreen(),
|
||||
),
|
||||
ShellRoute(
|
||||
builder: (context, state, child) => AppShell(child: child),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: '/stock-in',
|
||||
pageBuilder: (_, __) => _noTransition(const StockInListScreen())),
|
||||
GoRoute(
|
||||
path: '/stock-in/new',
|
||||
pageBuilder: (_, __) => _noTransition(const StockInFormScreen())),
|
||||
GoRoute(
|
||||
path: '/stock-in/edit/:id',
|
||||
pageBuilder: (_, state) => _noTransition(
|
||||
StockInFormScreen(
|
||||
editOrderId: int.parse(state.pathParameters['id']!)))),
|
||||
GoRoute(
|
||||
path: '/stock-out',
|
||||
pageBuilder: (_, __) => _noTransition(const StockOutListScreen())),
|
||||
GoRoute(
|
||||
path: '/stock-out/new',
|
||||
pageBuilder: (_, __) => _noTransition(const StockOutFormScreen())),
|
||||
GoRoute(
|
||||
path: '/stock-out/edit/:id',
|
||||
pageBuilder: (_, state) => _noTransition(
|
||||
StockOutFormScreen(
|
||||
editOrderId: int.parse(state.pathParameters['id']!)))),
|
||||
GoRoute(
|
||||
path: '/inventory',
|
||||
pageBuilder: (_, __) =>
|
||||
_noTransition(const InventoryListScreen())),
|
||||
GoRoute(
|
||||
path: '/inventory/check',
|
||||
pageBuilder: (_, __) =>
|
||||
_noTransition(const InventoryCheckScreen())),
|
||||
GoRoute(
|
||||
path: '/partners',
|
||||
pageBuilder: (_, __) => _noTransition(const PartnersScreen())),
|
||||
GoRoute(
|
||||
path: '/finance',
|
||||
pageBuilder: (_, __) => _noTransition(const FinanceScreen())),
|
||||
GoRoute(
|
||||
path: '/products',
|
||||
pageBuilder: (_, __) => _noTransition(const ProductsScreen())),
|
||||
GoRoute(
|
||||
path: '/products/:id',
|
||||
pageBuilder: (_, state) => _noTransition(ProductDetailScreen(
|
||||
productId: int.parse(state.pathParameters['id']!)))),
|
||||
GoRoute(
|
||||
path: '/settings',
|
||||
pageBuilder: (_, state) {
|
||||
const tabIndex = {
|
||||
'shop': 0,
|
||||
'users': 1,
|
||||
'number': 2,
|
||||
'system': 3,
|
||||
'license': 4,
|
||||
'import': 5,
|
||||
};
|
||||
final tab =
|
||||
tabIndex[state.uri.queryParameters['tab']] ?? 0;
|
||||
return _noTransition(SettingsScreen(initialTab: tab));
|
||||
}),
|
||||
GoRoute(
|
||||
path: '/devices',
|
||||
pageBuilder: (_, __) =>
|
||||
_noTransition(const DeviceManagementScreen())),
|
||||
GoRoute(
|
||||
path: '/about',
|
||||
pageBuilder: (_, __) => _noTransition(const AboutScreen())),
|
||||
// 各栏目拆为独立分支:StatefulShellRoute.indexedStack 让每个分支的 Navigator
|
||||
// 及其页面 State 常驻,跨栏目切换不再销毁上一页(半填表单/内部 tab/滚动位置保活)。
|
||||
// 分支顺序必须与 AppShell._navItems 一致(navigationShell.currentIndex 据此高亮)。
|
||||
StatefulShellRoute.indexedStack(
|
||||
builder: (context, state, navigationShell) =>
|
||||
AppShell(navigationShell: navigationShell),
|
||||
branches: [
|
||||
// 0 入库管理
|
||||
StatefulShellBranch(routes: [
|
||||
GoRoute(
|
||||
path: '/stock-in',
|
||||
pageBuilder: (_, __) =>
|
||||
_noTransition(const StockInListScreen())),
|
||||
GoRoute(
|
||||
path: '/stock-in/new',
|
||||
pageBuilder: (_, __) =>
|
||||
_noTransition(const StockInFormScreen())),
|
||||
GoRoute(
|
||||
path: '/stock-in/edit/:id',
|
||||
pageBuilder: (_, state) => _noTransition(StockInFormScreen(
|
||||
editOrderId: int.parse(state.pathParameters['id']!)))),
|
||||
]),
|
||||
// 1 出库管理
|
||||
StatefulShellBranch(routes: [
|
||||
GoRoute(
|
||||
path: '/stock-out',
|
||||
pageBuilder: (_, __) =>
|
||||
_noTransition(const StockOutListScreen())),
|
||||
GoRoute(
|
||||
path: '/stock-out/new',
|
||||
pageBuilder: (_, __) =>
|
||||
_noTransition(const StockOutFormScreen())),
|
||||
GoRoute(
|
||||
path: '/stock-out/edit/:id',
|
||||
pageBuilder: (_, state) => _noTransition(StockOutFormScreen(
|
||||
editOrderId: int.parse(state.pathParameters['id']!)))),
|
||||
]),
|
||||
// 2 库存管理
|
||||
StatefulShellBranch(routes: [
|
||||
GoRoute(
|
||||
path: '/inventory',
|
||||
pageBuilder: (_, __) =>
|
||||
_noTransition(const InventoryListScreen())),
|
||||
GoRoute(
|
||||
path: '/inventory/check',
|
||||
pageBuilder: (_, __) =>
|
||||
_noTransition(const InventoryCheckScreen())),
|
||||
]),
|
||||
// 3 财务管理
|
||||
StatefulShellBranch(routes: [
|
||||
GoRoute(
|
||||
path: '/finance',
|
||||
pageBuilder: (_, __) => _noTransition(const FinanceScreen())),
|
||||
]),
|
||||
// 4 往来单位
|
||||
StatefulShellBranch(routes: [
|
||||
GoRoute(
|
||||
path: '/partners',
|
||||
pageBuilder: (_, __) => _noTransition(const PartnersScreen())),
|
||||
]),
|
||||
// 5 基础数据
|
||||
StatefulShellBranch(routes: [
|
||||
GoRoute(
|
||||
path: '/products',
|
||||
pageBuilder: (_, __) => _noTransition(const ProductsScreen())),
|
||||
GoRoute(
|
||||
path: '/products/:id',
|
||||
pageBuilder: (_, state) => _noTransition(ProductDetailScreen(
|
||||
productId: int.parse(state.pathParameters['id']!)))),
|
||||
]),
|
||||
// 6 设备管理
|
||||
StatefulShellBranch(routes: [
|
||||
GoRoute(
|
||||
path: '/devices',
|
||||
pageBuilder: (_, __) =>
|
||||
_noTransition(const DeviceManagementScreen())),
|
||||
]),
|
||||
// 7 系统设置
|
||||
StatefulShellBranch(routes: [
|
||||
GoRoute(
|
||||
path: '/settings',
|
||||
pageBuilder: (_, state) {
|
||||
const tabIndex = {
|
||||
'shop': 0,
|
||||
'users': 1,
|
||||
'number': 2,
|
||||
'system': 3,
|
||||
'license': 4,
|
||||
'import': 5,
|
||||
};
|
||||
final tab = tabIndex[state.uri.queryParameters['tab']] ?? 0;
|
||||
return _noTransition(SettingsScreen(initialTab: tab));
|
||||
}),
|
||||
]),
|
||||
// 8 关于我们
|
||||
StatefulShellBranch(routes: [
|
||||
GoRoute(
|
||||
path: '/about',
|
||||
pageBuilder: (_, __) => _noTransition(const AboutScreen())),
|
||||
]),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user