Initial commit: 风影 OA 全栈源码(API/Web/Flutter/IM)
含 Phase 1.1 IM seq 排序、断线重连、多端已读同步与微信式语音转文字 UI。 排除 node_modules、构建产物、安装包与 .env 密钥。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import '../api/oa_client.dart';
|
||||
|
||||
class PushBridge {
|
||||
PushBridge._();
|
||||
static const _m = MethodChannel('com.fysxkj.oa/ota');
|
||||
static const _ev = EventChannel('com.fysxkj.oa/push');
|
||||
static StreamSubscription<dynamic>? _sub;
|
||||
|
||||
static Future<void> requestFirstLoginPermissions() async {
|
||||
try {
|
||||
await _m.invokeMethod('requestFirstLoginPermissions');
|
||||
} catch (_) {
|
||||
try {
|
||||
await _m.invokeMethod('requestPushPermission');
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> register(OaClient api) async {
|
||||
await requestFirstLoginPermissions();
|
||||
for (var i = 0; i < 10; i++) {
|
||||
try {
|
||||
final raw = await _m.invokeMethod('getPushToken');
|
||||
if (raw is Map) {
|
||||
final regId = '${raw['regId'] ?? ''}';
|
||||
if (regId.isNotEmpty) {
|
||||
await api.post('/push/devices', {
|
||||
'vendor': '${raw['vendor'] ?? 'vivo'}',
|
||||
'regId': regId,
|
||||
'brand': '${raw['brand'] ?? ''}',
|
||||
'model': '${raw['model'] ?? ''}',
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (_) {}
|
||||
await Future<void>.delayed(const Duration(seconds: 2));
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> showOnline(String title, String content, {Map<String, String> extras = const {}}) async {
|
||||
try {
|
||||
await _m.invokeMethod('showOnlineNotification', {'title': title, 'content': content, 'extras': extras});
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
static Future<Map<String, String>?> consumeLaunch() async {
|
||||
try {
|
||||
final raw = await _m.invokeMethod('consumeLaunchPush');
|
||||
if (raw is Map) return raw.map((k, v) => MapEntry('$k', '$v'));
|
||||
} catch (_) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
static void listen(void Function(Map<String, String>) onClick) {
|
||||
_sub?.cancel();
|
||||
_sub = _ev.receiveBroadcastStream().listen((event) {
|
||||
if (event is Map) {
|
||||
onClick(event.map((k, v) => MapEntry('$k', '$v')));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void stop() {
|
||||
_sub?.cancel();
|
||||
_sub = null;
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>?> oemStatus() async {
|
||||
try {
|
||||
final raw = await _m.invokeMethod('oemStatus');
|
||||
if (raw is Map) return Map<String, dynamic>.from(raw);
|
||||
} catch (_) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
static Future<void> openOemKeepAlive() async {
|
||||
try {
|
||||
await _m.invokeMethod('openOemKeepAlive');
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
static Future<void> requestBattery() async {
|
||||
try {
|
||||
await _m.invokeMethod('requestBattery');
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
static Future<void> markOemPrompted() async {
|
||||
try {
|
||||
await _m.invokeMethod('markOemPrompted');
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user