Files
daiyongkang 76f266645d Initial commit: 风影 OA 全栈源码(API/Web/Flutter/IM)
含 Phase 1.1 IM seq 排序、断线重连、多端已读同步与微信式语音转文字 UI。
排除 node_modules、构建产物、安装包与 .env 密钥。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-02 10:04:03 +00:00

104 lines
2.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:window_manager/window_manager.dart';
import 'api/oa_client.dart';
import 'app_runtime.dart';
import 'device/device_bridge.dart';
import 'desktop/desk_platform.dart';
import 'desktop/desk_theme.dart';
import 'pages/desktop_login_page.dart';
import 'pages/login_page.dart';
import 'session/session.dart';
import 'shell/home_shell.dart';
import 'theme.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await AppRuntime.load();
if (isDesktopPlatform) {
await windowManager.ensureInitialized();
const windowOptions = WindowOptions(
size: Size(1400, 900),
center: true,
title: '风影办公',
);
windowManager.waitUntilReadyToShow(windowOptions, () async {
await windowManager.show();
await windowManager.focus();
});
}
if (!isDesktopPlatform) {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: SystemUiOverlay.values);
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
statusBarColor: Colors.white,
statusBarIconBrightness: Brightness.dark,
));
DeviceBridge.preferMaxRefresh();
}
runApp(const FengyingApp());
}
class FengyingApp extends StatefulWidget {
const FengyingApp({super.key});
@override
State<FengyingApp> createState() => _FengyingAppState();
}
class _FengyingAppState extends State<FengyingApp> {
final session = SessionStore();
late final OaClient api = OaClient(session);
@override
void initState() {
super.initState();
DeviceBridge.bindApi(api);
session.addListener(_onSession);
_boot();
}
Future<void> _boot() async {
await session.load();
if (session.signedIn) {
try {
final me = await api.get('/auth/me');
if (me is Map) {
await session.patchUser(Map<String, dynamic>.from(me));
}
final menus = await api.get('/system/menus');
await session.setMenus(asMaps(menus).map(MenuNode.fromJson).toList());
await session.connectIm();
} catch (_) {
await session.clear();
}
}
}
void _onSession() => setState(() {});
@override
void dispose() {
session.removeListener(_onSession);
session.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '风影办公',
debugShowCheckedModeBanner: false,
theme: isDesktopPlatform ? buildDesktopTheme() : buildTheme(),
home: !session.loaded
? const Scaffold(backgroundColor: Colors.white, body: Center(child: CircularProgressIndicator(color: kBind)))
: session.signedIn
? HomeShell(session: session, api: api)
: isDesktopPlatform
? DesktopLoginPage(session: session, api: api)
: LoginPage(session: session, api: api),
);
}
}