Commit 30ca8815 authored by 张宏's avatar 张宏

1

parent 4e547344
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_secure_storage","path":"/Users/zh/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"/Users/zh/.pub-cache/hosted/pub.dev/fluttertoast-9.1.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/Users/zh/.pub-cache/hosted/pub.dev/path_provider_foundation-2.6.0/","native_build":false,"dependencies":[],"dev_dependency":false}],"android":[{"name":"flutter_secure_storage","path":"/Users/zh/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"/Users/zh/.pub-cache/hosted/pub.dev/fluttertoast-9.1.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"jni","path":"/Users/zh/.pub-cache/hosted/pub.dev/jni-1.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"jni_flutter","path":"/Users/zh/.pub-cache/hosted/pub.dev/jni_flutter-1.0.1/","native_build":true,"dependencies":["jni"],"dev_dependency":false},{"name":"path_provider_android","path":"/Users/zh/.pub-cache/hosted/pub.dev/path_provider_android-2.3.1/","native_build":false,"dependencies":["jni","jni_flutter"],"dev_dependency":false}],"macos":[{"name":"flutter_secure_storage_macos","path":"/Users/zh/.pub-cache/hosted/pub.dev/flutter_secure_storage_macos-3.1.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/Users/zh/.pub-cache/hosted/pub.dev/path_provider_foundation-2.6.0/","native_build":false,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"flutter_secure_storage_linux","path":"/Users/zh/.pub-cache/hosted/pub.dev/flutter_secure_storage_linux-1.2.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"jni","path":"/Users/zh/.pub-cache/hosted/pub.dev/jni-1.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_linux","path":"/Users/zh/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[],"dev_dependency":false}],"windows":[{"name":"flutter_secure_storage_windows","path":"/Users/zh/.pub-cache/hosted/pub.dev/flutter_secure_storage_windows-3.1.2/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"jni","path":"/Users/zh/.pub-cache/hosted/pub.dev/jni-1.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_windows","path":"/Users/zh/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[],"dev_dependency":false}],"web":[{"name":"flutter_secure_storage_web","path":"/Users/zh/.pub-cache/hosted/pub.dev/flutter_secure_storage_web-1.2.1/","dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"/Users/zh/.pub-cache/hosted/pub.dev/fluttertoast-9.1.0/","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"flutter_secure_storage","dependencies":["flutter_secure_storage_linux","flutter_secure_storage_macos","flutter_secure_storage_web","flutter_secure_storage_windows"]},{"name":"flutter_secure_storage_linux","dependencies":[]},{"name":"flutter_secure_storage_macos","dependencies":[]},{"name":"flutter_secure_storage_web","dependencies":[]},{"name":"flutter_secure_storage_windows","dependencies":["path_provider"]},{"name":"fluttertoast","dependencies":[]},{"name":"jni","dependencies":[]},{"name":"jni_flutter","dependencies":["jni"]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":["jni","jni_flutter"]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2026-06-15 16:07:29.493993","version":"3.41.9","swift_package_manager_enabled":{"ios":false,"macos":false}}
\ No newline at end of file
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_secure_storage","path":"/Users/zh/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"/Users/zh/.pub-cache/hosted/pub.dev/fluttertoast-9.1.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/Users/zh/.pub-cache/hosted/pub.dev/path_provider_foundation-2.6.0/","native_build":false,"dependencies":[],"dev_dependency":false}],"android":[{"name":"flutter_secure_storage","path":"/Users/zh/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.4/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"/Users/zh/.pub-cache/hosted/pub.dev/fluttertoast-9.1.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"jni","path":"/Users/zh/.pub-cache/hosted/pub.dev/jni-1.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"jni_flutter","path":"/Users/zh/.pub-cache/hosted/pub.dev/jni_flutter-1.0.1/","native_build":true,"dependencies":["jni"],"dev_dependency":false},{"name":"path_provider_android","path":"/Users/zh/.pub-cache/hosted/pub.dev/path_provider_android-2.3.1/","native_build":false,"dependencies":["jni","jni_flutter"],"dev_dependency":false}],"macos":[{"name":"flutter_secure_storage_macos","path":"/Users/zh/.pub-cache/hosted/pub.dev/flutter_secure_storage_macos-3.1.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/Users/zh/.pub-cache/hosted/pub.dev/path_provider_foundation-2.6.0/","native_build":false,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"flutter_secure_storage_linux","path":"/Users/zh/.pub-cache/hosted/pub.dev/flutter_secure_storage_linux-1.2.3/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"jni","path":"/Users/zh/.pub-cache/hosted/pub.dev/jni-1.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_linux","path":"/Users/zh/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[],"dev_dependency":false}],"windows":[{"name":"flutter_secure_storage_windows","path":"/Users/zh/.pub-cache/hosted/pub.dev/flutter_secure_storage_windows-3.1.2/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"jni","path":"/Users/zh/.pub-cache/hosted/pub.dev/jni-1.0.0/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_windows","path":"/Users/zh/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[],"dev_dependency":false}],"web":[{"name":"flutter_secure_storage_web","path":"/Users/zh/.pub-cache/hosted/pub.dev/flutter_secure_storage_web-1.2.1/","dependencies":[],"dev_dependency":false},{"name":"fluttertoast","path":"/Users/zh/.pub-cache/hosted/pub.dev/fluttertoast-9.1.0/","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"flutter_secure_storage","dependencies":["flutter_secure_storage_linux","flutter_secure_storage_macos","flutter_secure_storage_web","flutter_secure_storage_windows"]},{"name":"flutter_secure_storage_linux","dependencies":[]},{"name":"flutter_secure_storage_macos","dependencies":[]},{"name":"flutter_secure_storage_web","dependencies":[]},{"name":"flutter_secure_storage_windows","dependencies":["path_provider"]},{"name":"fluttertoast","dependencies":[]},{"name":"jni","dependencies":[]},{"name":"jni_flutter","dependencies":["jni"]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":["jni","jni_flutter"]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2026-06-16 09:58:23.239196","version":"3.41.9","swift_package_manager_enabled":{"ios":false,"macos":false}}
\ No newline at end of file
......@@ -80,4 +80,4 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
}
}
}
}
\ No newline at end of file
}
......@@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:smart_hotel_app/blocs/auth/auth_bloc.dart';
import 'package:smart_hotel_app/blocs/auth/auth_event.dart';
import 'package:smart_hotel_app/blocs/auth/auth_state.dart';
import 'package:smart_hotel_app/blocs/auth/auth_state.dart';
import 'package:smart_hotel_app/routes/app_router.dart';
import 'package:smart_hotel_app/repositories/auth_repository.dart';
import 'package:smart_hotel_app/services/auth_service.dart';
......@@ -12,7 +12,7 @@ import 'package:smart_hotel_app/utils/event_bus.dart';
import 'package:smart_hotel_app/utils/storage/storage_service.dart';
import 'package:smart_hotel_app/utils/toast_utils.dart';
import 'package:smart_hotel_app/routes/app_router.gr.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
void main(List<String> args) {
WidgetsFlutterBinding.ensureInitialized();
......
......@@ -41,4 +41,4 @@ class LoginBO extends Equatable {
refreshExpireIn,
clientId,
];
}
\ No newline at end of file
}
import 'package:equatable/equatable.dart';
/// 用途:首页监护舱顶部环境与护理指标数据
/// 涉及页面:首页监护舱页面
class MonitoringMetricBO extends Equatable {
/// 指标数值
final String value;
/// 指标单位
final String unit;
/// 指标名称
final String label;
/// 指标边框颜色值
final int borderColorValue;
/// 指标背景颜色值
final int backgroundColorValue;
const MonitoringMetricBO({
required this.value,
required this.unit,
required this.label,
this.borderColorValue = 0xFF999999,
this.backgroundColorValue = 0x1A999999,
});
factory MonitoringMetricBO.fromJson(Map<String, dynamic> json) {
return MonitoringMetricBO(
value: json['value'] as String? ?? '',
unit: json['unit'] as String? ?? '',
label: json['label'] as String? ?? '',
borderColorValue: json['borderColorValue'] as int? ?? 0xFF999999,
backgroundColorValue: json['backgroundColorValue'] as int? ?? 0x1A999999,
);
}
@override
List<Object?> get props => [
value,
unit,
label,
borderColorValue,
backgroundColorValue,
];
}
/// 用途:首页监护舱患者信息展示数据
/// 涉及页面:首页监护舱页面
class PatientInfoBO extends Equatable {
/// 患者名称
final String name;
/// 家长信息
final String owner;
/// 联系电话
final String phone;
/// 患者品种
final String breed;
/// 负责医生
final String doctor;
/// 患者头像地址
final String avatarUrl;
const PatientInfoBO({
required this.name,
required this.owner,
required this.phone,
required this.breed,
required this.doctor,
this.avatarUrl = '',
});
factory PatientInfoBO.fromJson(Map<String, dynamic> json) {
return PatientInfoBO(
name: json['name'] as String? ?? '',
owner: json['owner'] as String? ?? '',
phone: json['phone'] as String? ?? '',
breed: json['breed'] as String? ?? '',
doctor: json['doctor'] as String? ?? '',
avatarUrl: json['avatarUrl'] as String? ?? '',
);
}
@override
List<Object?> get props => [name, owner, phone, breed, doctor, avatarUrl];
}
/// 用途:首页监护舱告警信息展示数据
/// 涉及页面:首页监护舱页面
class AlertInfoBO extends Equatable {
/// 告警标题
final String title;
/// 告警描述
final String description;
/// 告警时间
final String time;
/// 告警处理状态
final String status;
const AlertInfoBO({
required this.title,
required this.description,
required this.time,
this.status = '已处理',
});
factory AlertInfoBO.fromJson(Map<String, dynamic> json) {
return AlertInfoBO(
title: json['title'] as String? ?? '',
description: json['description'] as String? ?? '',
time: json['time'] as String? ?? '',
status: json['status'] as String? ?? '已处理',
);
}
@override
List<Object?> get props => [title, description, time, status];
}
/// 用途:首页监护舱右侧设备菜单数据
/// 涉及页面:首页监护舱页面
class MonitoringMenuItemBO extends Equatable {
/// 菜单标题
final String title;
/// 菜单图标文案
final String icon;
const MonitoringMenuItemBO({
required this.title,
required this.icon,
});
factory MonitoringMenuItemBO.fromJson(Map<String, dynamic> json) {
return MonitoringMenuItemBO(
title: json['title'] as String? ?? '',
icon: json['icon'] as String? ?? '',
);
}
@override
List<Object?> get props => [title, icon];
}
......@@ -63,4 +63,4 @@ class UserInfoBO extends Equatable {
deptName,
tenantId,
];
}
\ No newline at end of file
}
import '../../models/bo/monitoring_bo.dart';
/// 首页监护舱模块本地 mock 数据。
///
/// 所有 mock 数据直接使用 models 层的构造函数创建,
/// 确保数据结构与 models 定义完全一致。
/// 后续接入真实接口时,只需修改 Repository 层的开关即可。
class MonitoringMockData {
MonitoringMockData._();
static List<MonitoringMetricBO> getMockMetrics() {
return const [
MonitoringMetricBO(
value: '24',
unit: '℃',
label: '舱内温度',
borderColorValue: 0xFF00FF9D,
backgroundColorValue: 0x1A00FF9D,
),
MonitoringMetricBO(
value: '63',
unit: '%',
label: '舱内湿度',
),
MonitoringMetricBO(
value: '21',
unit: '%',
label: '氧浓度',
),
MonitoringMetricBO(
value: '531',
unit: 'PPM',
label: 'CO₂浓度',
borderColorValue: 0xFF00FF9D,
backgroundColorValue: 0x1A00FF9D,
),
MonitoringMetricBO(
value: '特级',
unit: '',
label: '护理等级',
borderColorValue: 0xFFFF7D00,
backgroundColorValue: 0x1AFF7D00,
),
];
}
static PatientInfoBO getMockPatientInfo() {
return const PatientInfoBO(
name: '妮蔻 Niko',
owner: '家长:王女士',
phone: '联系电话:15845310589',
breed: '品种:长毛三花',
doctor: '医生:程医生',
avatarUrl: 'https://example.com/avatar/cat.png',
);
}
static List<AlertInfoBO> getMockAlerts() {
return const [
AlertInfoBO(
title: '温度异常',
description: '温度高于阈值26℃,当前温度29℃',
time: '2026-05-04 16:22:49',
status: '待处理',
),
];
}
static List<MonitoringMenuItemBO> getMockMenuItems() {
return const [
MonitoringMenuItemBO(
title: 'TSAAS 动物血压监测',
icon: '❤️',
),
MonitoringMenuItemBO(
title: 'TSAAS 多功能动物体征检测仪',
icon: '📏',
),
MonitoringMenuItemBO(
title: 'TSAAS+CATHAER 穿戴式多导心电监测系统',
icon: '❤️',
),
];
}
}
import 'mock/monitoring_mock_data.dart';
import 'package:smart_hotel_app/models/bo/monitoring_bo.dart';
import 'package:smart_hotel_app/utils/constants.dart';
import 'package:smart_hotel_app/utils/http/dio_request.dart';
import 'package:smart_hotel_app/utils/http/response_model.dart';
class MonitoringRepository {
MonitoringRepository._();
static final MonitoringRepository instance = MonitoringRepository._();
Future<ResponseModel<List<MonitoringMetricBO>>> getMetrics() {
if (Constants.useMockData) {
return _mockMetrics();
}
return DioRequest.instance.get<List<MonitoringMetricBO>>(
'/app/monitoring/metrics',
fromJsonT: (data) {
final list = data as List<dynamic>;
return list
.map((e) => MonitoringMetricBO.fromJson(e as Map<String, dynamic>))
.toList();
},
);
}
Future<ResponseModel<PatientInfoBO>> getPatientInfo() {
if (Constants.useMockData) {
return _mockPatientInfo();
}
return DioRequest.instance.get<PatientInfoBO>(
'/app/monitoring/patient-info',
fromJsonT: (data) => PatientInfoBO.fromJson(data as Map<String, dynamic>),
);
}
Future<ResponseModel<List<AlertInfoBO>>> getAlerts() {
if (Constants.useMockData) {
return _mockAlerts();
}
return DioRequest.instance.get<List<AlertInfoBO>>(
'/app/monitoring/alerts',
fromJsonT: (data) {
final list = data as List<dynamic>;
return list
.map((e) => AlertInfoBO.fromJson(e as Map<String, dynamic>))
.toList();
},
);
}
Future<ResponseModel<List<MonitoringMenuItemBO>>> getMenuItems() {
if (Constants.useMockData) {
return _mockMenuItems();
}
return DioRequest.instance.get<List<MonitoringMenuItemBO>>(
'/app/monitoring/menu-items',
fromJsonT: (data) {
final list = data as List<dynamic>;
return list
.map(
(e) => MonitoringMenuItemBO.fromJson(e as Map<String, dynamic>))
.toList();
},
);
}
Future<ResponseModel<List<MonitoringMetricBO>>> _mockMetrics() async {
await Future.delayed(const Duration(milliseconds: 300));
return ResponseModel<List<MonitoringMetricBO>>(
code: 200,
msg: '获取监护指标成功(mock)',
data: MonitoringMockData.getMockMetrics(),
uuid: 'mock_uuid_${DateTime.now().millisecondsSinceEpoch}',
success: true,
timestamp: DateTime.now().millisecondsSinceEpoch,
);
}
Future<ResponseModel<PatientInfoBO>> _mockPatientInfo() async {
await Future.delayed(const Duration(milliseconds: 300));
return ResponseModel<PatientInfoBO>(
code: 200,
msg: '获取患者信息成功(mock)',
data: MonitoringMockData.getMockPatientInfo(),
uuid: 'mock_uuid_${DateTime.now().millisecondsSinceEpoch}',
success: true,
timestamp: DateTime.now().millisecondsSinceEpoch,
);
}
Future<ResponseModel<List<AlertInfoBO>>> _mockAlerts() async {
await Future.delayed(const Duration(milliseconds: 300));
return ResponseModel<List<AlertInfoBO>>(
code: 200,
msg: '获取告警信息成功(mock)',
data: MonitoringMockData.getMockAlerts(),
uuid: 'mock_uuid_${DateTime.now().millisecondsSinceEpoch}',
success: true,
timestamp: DateTime.now().millisecondsSinceEpoch,
);
}
Future<ResponseModel<List<MonitoringMenuItemBO>>> _mockMenuItems() async {
await Future.delayed(const Duration(milliseconds: 300));
return ResponseModel<List<MonitoringMenuItemBO>>(
code: 200,
msg: '获取设备菜单成功(mock)',
data: MonitoringMockData.getMockMenuItems(),
uuid: 'mock_uuid_${DateTime.now().millisecondsSinceEpoch}',
success: true,
timestamp: DateTime.now().millisecondsSinceEpoch,
);
}
}
import 'package:auto_route/auto_route.dart';
import 'package:smart_hotel_app/routes/app_router.gr.dart';
import 'package:smart_hotel_app/views/home/index/home_index_view.dart';
import 'package:smart_hotel_app/views/login/login_view.dart';
import 'package:smart_hotel_app/views/layout/default_view.dart';
import 'app_router.gr.dart';
@AutoRouterConfig(replaceInRouteName: 'View,Route')
class AppRouter extends $AppRouter {
......@@ -16,7 +19,7 @@ class AppRouter extends $AppRouter {
page: DefaultLayoutRoute.page,
children: [
// HomeRoute / HomeView(首页)
AutoRoute(page: HomeRoute.page, initial: true),
AutoRoute(page: HomeIndexRoute.page, initial: true),
],
),
];
......
......@@ -10,7 +10,7 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:auto_route/auto_route.dart' as _i4;
import 'package:flutter/material.dart' as _i5;
import 'package:smart_hotel_app/views/home/index/index_view.dart' as _i2;
import 'package:smart_hotel_app/views/home/index/home_index_view.dart' as _i2;
import 'package:smart_hotel_app/views/layout/default_view.dart' as _i1;
import 'package:smart_hotel_app/views/login/login_view.dart' as _i3;
......@@ -25,10 +25,10 @@ abstract class $AppRouter extends _i4.RootStackRouter {
child: const _i1.DefaultLayoutView(),
);
},
HomeRoute.name: (routeData) {
HomeIndexRoute.name: (routeData) {
return _i4.AutoRoutePage<dynamic>(
routeData: routeData,
child: const _i2.HomeView(),
child: const _i2.HomeIndexView(),
);
},
LoginRoute.name: (routeData) {
......@@ -57,15 +57,15 @@ class DefaultLayoutRoute extends _i4.PageRouteInfo<void> {
}
/// generated route for
/// [_i2.HomeView]
class HomeRoute extends _i4.PageRouteInfo<void> {
const HomeRoute({List<_i4.PageRouteInfo>? children})
/// [_i2.HomeIndexView]
class HomeIndexRoute extends _i4.PageRouteInfo<void> {
const HomeIndexRoute({List<_i4.PageRouteInfo>? children})
: super(
HomeRoute.name,
HomeIndexRoute.name,
initialChildren: children,
);
static const String name = 'HomeRoute';
static const String name = 'HomeIndexRoute';
static const _i4.PageInfo<void> page = _i4.PageInfo<void>(name);
}
......
......@@ -60,4 +60,4 @@ class AuthService {
Future<bool> isTokenExpired() async {
return _storageService.isTokenExpired();
}
}
\ No newline at end of file
}
import 'package:smart_hotel_app/models/bo/monitoring_bo.dart';
import 'package:smart_hotel_app/repositories/monitoring_repository.dart';
class MonitoringService {
final MonitoringRepository _repository;
MonitoringService() : _repository = MonitoringRepository.instance;
Future<List<MonitoringMetricBO>> getMetrics() async {
final result = await _repository.getMetrics();
if (result.success && result.data != null) {
return result.data!;
}
throw Exception(result.msg);
}
Future<PatientInfoBO> getPatientInfo() async {
final result = await _repository.getPatientInfo();
if (result.success && result.data != null) {
return result.data!;
}
throw Exception(result.msg);
}
Future<List<AlertInfoBO>> getAlerts() async {
final result = await _repository.getAlerts();
if (result.success && result.data != null) {
return result.data!;
}
throw Exception(result.msg);
}
Future<List<MonitoringMenuItemBO>> getMenuItems() async {
final result = await _repository.getMenuItems();
if (result.success && result.data != null) {
return result.data!;
}
throw Exception(result.msg);
}
}
class Constants {
// ==================== 环境配置 ====================
/// 当前环境:dev / staging / prod,通过 --dart-define=APP_ENV=xxx 注入
static const String env = String.fromEnvironment('APP_ENV', defaultValue: 'dev');
static const String env =
String.fromEnvironment('APP_ENV', defaultValue: 'dev');
/// API 地址,由 env/*.json 中的 SERVICE_URL 注入
static String get baseUrl => const String.fromEnvironment('SERVICE_URL');
// ==================== 超时配置 ====================
static const int connectTimeout = 30000;
......
......@@ -383,4 +383,4 @@ class DioRequest {
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
return List.generate(length, (index) => chars[index % chars.length]).join();
}
}
\ No newline at end of file
}
......@@ -13,4 +13,4 @@ class AppException implements Exception {
String toString() {
return 'AppException: $message (code: $code, uuid: $uuid)';
}
}
\ No newline at end of file
}
......@@ -6,4 +6,4 @@ class BusinessException extends AppException {
int? code,
String? uuid,
}) : super(message: message, code: code, uuid: uuid);
}
\ No newline at end of file
}
......@@ -5,4 +5,4 @@ class CancelException extends AppException {
String message = '请求已取消',
String? uuid,
}) : super(message: message, code: -1, uuid: uuid);
}
\ No newline at end of file
}
......@@ -6,4 +6,4 @@ class NetworkException extends AppException {
int? code,
String? uuid,
}) : super(message: message, code: code, uuid: uuid);
}
\ No newline at end of file
}
......@@ -6,4 +6,4 @@ class ServerException extends AppException {
int? code,
String? uuid,
}) : super(message: message, code: code, uuid: uuid);
}
\ No newline at end of file
}
......@@ -138,4 +138,4 @@ class ErrorInterceptor extends Interceptor {
}
Log.error('========== Error END ==========');
}
}
\ No newline at end of file
}
......@@ -59,4 +59,4 @@ class RequestInterceptor extends Interceptor {
}
Log.info('********************** Request END **********************');
}
}
\ No newline at end of file
}
......@@ -18,4 +18,4 @@ class ResponseInterceptor extends Interceptor {
Log.warn('Data: ${response.data}');
Log.warn('====================== Response END ======================');
}
}
\ No newline at end of file
}
......@@ -81,4 +81,4 @@ class ResponseModel<T> {
String toString() {
return 'ResponseModel(code: $code, msg: $msg, uuid: $uuid, success: $success)';
}
}
\ No newline at end of file
}
......@@ -37,7 +37,8 @@ class _LongMessagePrinter extends pkg.LogPrinter {
if (text.length <= _chunkSize) return [text];
final chunks = <String>[];
for (var i = 0; i < text.length; i += _chunkSize) {
chunks.add(text.substring(i, i + _chunkSize > text.length ? text.length : i + _chunkSize));
chunks.add(text.substring(
i, i + _chunkSize > text.length ? text.length : i + _chunkSize));
}
return chunks;
}
......@@ -46,7 +47,8 @@ class _LongMessagePrinter extends pkg.LogPrinter {
List<String> log(pkg.LogEvent event) {
final original = event.message;
final output = StringBuffer();
final lines = const LineSplitter().convert(_tryPrettyJson(original.toString()));
final lines =
const LineSplitter().convert(_tryPrettyJson(original.toString()));
for (final line in lines) {
for (final chunk in _chunk(line)) {
output.writeln(chunk);
......
......@@ -127,4 +127,4 @@ class StorageService {
Future<void> clearAll() async {
await _storage.deleteAll();
}
}
\ No newline at end of file
}
library tcp;
export 'service/index.dart';
\ No newline at end of file
export 'service/index.dart';
......@@ -2,4 +2,4 @@ export 'tcp_client_cubit.dart';
export 'tcp_client_state.dart';
export 'tcp_server_cubit.dart';
export 'tcp_server_state.dart';
export 'tcp_connection_status.dart';
\ No newline at end of file
export 'tcp_connection_status.dart';
......@@ -20,7 +20,8 @@ class TcpClientCubit extends Cubit<TcpClientState> {
bool _isManualDisconnect = false;
bool _isConnecting = false;
final StreamController<Uint8List> _dataController = StreamController.broadcast();
final StreamController<Uint8List> _dataController =
StreamController.broadcast();
/// 接收到的数据流
Stream<Uint8List> get onData => _dataController.stream;
......@@ -54,7 +55,8 @@ class TcpClientCubit extends Cubit<TcpClientState> {
_isConnecting = true;
_isManualDisconnect = false;
emit(state.copyWith(connectionStatus: TcpConnectionStatus.connecting, clearError: true));
emit(state.copyWith(
connectionStatus: TcpConnectionStatus.connecting, clearError: true));
try {
_socket = await Socket.connect(
......@@ -182,4 +184,4 @@ class TcpClientCubit extends Cubit<TcpClientState> {
_dataController.close();
return super.close();
}
}
\ No newline at end of file
}
......@@ -33,4 +33,4 @@ class TcpClientState extends Equatable {
@override
List<Object?> get props => [connectionStatus, address, port, error];
}
\ No newline at end of file
}
......@@ -14,4 +14,4 @@ enum TcpConnectionStatus {
/// 错误
error,
}
\ No newline at end of file
}
......@@ -8,7 +8,8 @@ class TcpServerCubit extends Cubit<TcpServerState> {
ServerSocket? _serverSocket;
final List<Socket> _clients = [];
final StreamController<Map<String, dynamic>> _dataController = StreamController.broadcast();
final StreamController<Map<String, dynamic>> _dataController =
StreamController.broadcast();
/// 接收到的客户端数据流
Stream<Map<String, dynamic>> get onClientData => _dataController.stream;
......@@ -23,7 +24,8 @@ class TcpServerCubit extends Cubit<TcpServerState> {
/// 启动服务端
Future<void> start() async {
try {
_serverSocket = await ServerSocket.bind(InternetAddress.anyIPv4, state.port);
_serverSocket =
await ServerSocket.bind(InternetAddress.anyIPv4, state.port);
emit(state.copyWith(isRunning: true, port: _serverSocket!.port));
_listenClients();
} catch (e) {
......@@ -103,4 +105,4 @@ class TcpServerCubit extends Cubit<TcpServerState> {
_dataController.close();
return super.close();
}
}
\ No newline at end of file
}
......@@ -30,4 +30,4 @@ class TcpServerState extends Equatable {
@override
List<Object?> get props => [isRunning, port, connectedClients, error];
}
\ No newline at end of file
}
......@@ -12,4 +12,4 @@ void showToast(String msg) {
textColor: const Color(0xFFFFFFFF),
fontSize: 16.0,
);
}
\ No newline at end of file
}
import 'package:bloc/bloc.dart';
import 'package:smart_hotel_app/services/monitoring_service.dart';
import 'home_index_state.dart';
class HomeIndexCubit extends Cubit<HomeIndexState> {
final MonitoringService _monitoringService;
HomeIndexCubit()
: _monitoringService = MonitoringService(),
super(const HomeIndexState()) {
loadData();
}
Future<void> loadData() async {
emit(state.copyWith(isLoading: true, error: null));
try {
final metrics = await _monitoringService.getMetrics();
final patientInfo = await _monitoringService.getPatientInfo();
final alerts = await _monitoringService.getAlerts();
final menuItems = await _monitoringService.getMenuItems();
emit(state.copyWith(
isLoading: false,
status: HomeIndexStatus.success,
metrics: metrics,
patientInfo: patientInfo,
alerts: alerts,
menuItems: menuItems,
error: null,
));
} catch (e) {
emit(state.copyWith(
isLoading: false,
status: HomeIndexStatus.failure,
error: e.toString(),
));
}
}
Future<void> refreshData() async {
try {
final metrics = await _monitoringService.getMetrics();
final patientInfo = await _monitoringService.getPatientInfo();
final alerts = await _monitoringService.getAlerts();
final menuItems = await _monitoringService.getMenuItems();
emit(state.copyWith(
status: HomeIndexStatus.success,
metrics: metrics,
patientInfo: patientInfo,
alerts: alerts,
menuItems: menuItems,
error: null,
));
} catch (e) {
emit(state.copyWith(
status: HomeIndexStatus.failure,
error: e.toString(),
));
}
}
}
import 'package:equatable/equatable.dart';
import 'package:smart_hotel_app/models/bo/monitoring_bo.dart';
enum HomeIndexStatus {
initial,
loading,
success,
failure,
}
class HomeIndexState extends Equatable {
final HomeIndexStatus status;
final bool isLoading;
final String? error;
final List<MonitoringMetricBO> metrics;
final PatientInfoBO? patientInfo;
final List<AlertInfoBO> alerts;
final List<MonitoringMenuItemBO> menuItems;
const HomeIndexState({
this.status = HomeIndexStatus.initial,
this.isLoading = false,
this.error,
this.metrics = const [],
this.patientInfo,
this.alerts = const [],
this.menuItems = const [],
});
HomeIndexState copyWith({
HomeIndexStatus? status,
bool? isLoading,
String? error,
List<MonitoringMetricBO>? metrics,
PatientInfoBO? patientInfo,
List<AlertInfoBO>? alerts,
List<MonitoringMenuItemBO>? menuItems,
}) {
return HomeIndexState(
status: status ?? this.status,
isLoading: isLoading ?? this.isLoading,
error: error ?? this.error,
metrics: metrics ?? this.metrics,
patientInfo: patientInfo ?? this.patientInfo,
alerts: alerts ?? this.alerts,
menuItems: menuItems ?? this.menuItems,
);
}
@override
List<Object?> get props => [
status,
isLoading,
error,
metrics,
patientInfo,
alerts,
menuItems,
];
}
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/models/bo/monitoring_bo.dart';
import 'cubit/home_index_cubit.dart';
import 'cubit/home_index_state.dart';
import 'widgets/alert_info_card.dart';
import 'widgets/metric_card.dart';
import 'widgets/monitoring_screen.dart';
import 'widgets/patient_info_card.dart';
import 'widgets/sidebar_menu_item.dart';
@RoutePage()
class HomeIndexView extends StatelessWidget {
const HomeIndexView({super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => HomeIndexCubit(),
child: const HomeIndexContent(),
);
}
}
class HomeIndexContent extends StatefulWidget {
const HomeIndexContent({super.key});
@override
State<HomeIndexContent> createState() => _HomeIndexContentState();
}
class _HomeIndexContentState extends State<HomeIndexContent> {
late final HomeIndexCubit _homeIndexCubit;
@override
void initState() {
super.initState();
_homeIndexCubit = context.read<HomeIndexCubit>();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFF0F1F47),
body: SafeArea(
child: Column(
children: [
_buildAppBar(),
Expanded(
child: BlocBuilder<HomeIndexCubit, HomeIndexState>(
builder: (context, state) {
if (state.isLoading && state.metrics.isEmpty) {
return const Center(
child: CircularProgressIndicator(color: Colors.white),
);
}
if (state.status == HomeIndexStatus.failure &&
state.metrics.isEmpty) {
return _buildError(state.error);
}
return _buildMainContent(state);
},
),
),
_buildFooter(),
],
),
),
);
}
Widget _buildError(String? error) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'加载失败: ${error ?? '未知错误'}',
style: TextStyle(color: Colors.white, fontSize: 24.sp),
),
SizedBox(height: 24.h),
ElevatedButton(
onPressed: () => _homeIndexCubit.loadData(),
child: const Text('重试'),
),
],
),
);
}
Widget _buildAppBar() {
return Container(
padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 12.h),
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xFF1E10B6), Color(0xFF3A87FF)],
),
border: Border(bottom: BorderSide(color: Colors.white24, width: 1)),
),
child: Row(
children: [
SizedBox(width: 24.w),
const CircleAvatar(
backgroundColor: Colors.white,
radius: 24,
),
SizedBox(width: 16.w),
Text(
'加邦TSAAS动物医疗监护舱',
style: TextStyle(
fontSize: 32.sp,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
const Spacer(),
_buildAppBarIcon(Icons.bluetooth, 'TSAAS'),
SizedBox(width: 24.w),
_buildAppBarIcon(Icons.description, null),
SizedBox(width: 24.w),
_buildAppBarIcon(Icons.settings, null),
SizedBox(width: 16.w),
],
),
);
}
Widget _buildAppBarIcon(IconData icon, String? label) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
decoration: BoxDecoration(
border: Border.all(color: Colors.white24, width: 1),
borderRadius: BorderRadius.circular(20.r),
),
child: Row(
children: [
Icon(icon, color: Colors.white, size: 24.w),
if (label != null) ...[
SizedBox(width: 8.w),
Text(
label,
style: TextStyle(
fontSize: 22.sp,
color: Colors.white,
),
),
],
],
),
);
}
Widget _buildMainContent(HomeIndexState state) {
return SingleChildScrollView(
padding: EdgeInsets.all(24.w),
child: Column(
children: [
_buildMetricsSection(state.metrics),
SizedBox(height: 24.h),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 3,
child: Column(
children: [
MonitoringScreen(
onRefresh: () => _homeIndexCubit.refreshData(),
onSnapshot: () {},
onRecord: () {},
),
SizedBox(height: 24.h),
Row(
children: [
Expanded(
flex: 2,
child: state.patientInfo == null
? _buildEmptyCard('暂无患者信息')
: PatientInfoCard(
patientInfo: state.patientInfo!,
),
),
SizedBox(width: 24.w),
Expanded(
flex: 1,
child: AlertInfoCard(alerts: state.alerts),
),
],
),
],
),
),
SizedBox(width: 24.w),
Expanded(
flex: 1,
child: Column(
children: state.menuItems.map((item) {
return Padding(
padding: EdgeInsets.only(bottom: 24.h),
child: SidebarMenuItem(
item: item,
onTap: () {},
),
);
}).toList(),
),
),
],
),
],
),
);
}
Widget _buildEmptyCard(String text) {
return Container(
padding: EdgeInsets.all(24.w),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFF1E10B6), Color(0xFF3A87FF)],
),
borderRadius: BorderRadius.circular(20.r),
border: Border.all(color: Colors.white24, width: 1),
),
child: Center(
child: Text(
text,
style: TextStyle(color: Colors.white70, fontSize: 24.sp),
),
),
);
}
Widget _buildMetricsSection(List<MonitoringMetricBO> metrics) {
return Container(
padding: EdgeInsets.all(24.w),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFF1E10B6), Color(0xFF3A87FF)],
),
borderRadius: BorderRadius.circular(20.r),
border: Border.all(color: Colors.white24, width: 1),
),
child: Row(
children: metrics.map((metric) {
return Expanded(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 8.w),
child: MetricCard(metric: metric),
),
);
}).toList(),
),
);
}
Widget _buildFooter() {
return Container(
padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 12.h),
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xFF1E10B6), Color(0xFF3A87FF)],
),
border: Border(top: BorderSide(color: Colors.white24, width: 1)),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'总运行时长: 35 h',
style: TextStyle(
fontSize: 24.sp,
color: Colors.white70,
),
),
Text(
'环境温度: 25.6 ℃',
style: TextStyle(
fontSize: 24.sp,
color: Colors.white70,
),
),
],
),
);
}
}
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
@RoutePage()
class HomeView extends StatelessWidget {
const HomeView({super.key});
@override
Widget build(BuildContext context) {
return const Center(
child: Text("你好"),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/models/bo/monitoring_bo.dart';
class AlertInfoCard extends StatelessWidget {
final List<AlertInfoBO> alerts;
const AlertInfoCard({
super.key,
required this.alerts,
});
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(24.w),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFF1E10B6), Color(0xFF3A87FF)],
),
borderRadius: BorderRadius.circular(20.r),
border: Border.all(color: Colors.white24, width: 1),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'告警信息',
style: TextStyle(
fontSize: 28.sp,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
if (alerts.isNotEmpty) _buildStatus(alerts.first.status),
],
),
SizedBox(height: 16.h),
if (alerts.isNotEmpty)
...alerts.map((alert) => _buildAlertItem(alert))
else
Text(
'暂无告警信息',
style: TextStyle(color: Colors.white70, fontSize: 22.sp),
),
SizedBox(height: 8.h),
Align(
alignment: Alignment.centerRight,
child: TextButton(
onPressed: () {},
child: Text(
'详情 >',
style: TextStyle(
fontSize: 22.sp,
color: Colors.white70,
),
),
),
),
],
),
);
}
Widget _buildStatus(String status) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 4.h),
decoration: BoxDecoration(
color: const Color(0xFFFFB800),
borderRadius: BorderRadius.circular(20.r),
),
child: Text(
status,
style: TextStyle(
fontSize: 20.sp,
color: Colors.white,
fontWeight: FontWeight.w500,
),
),
);
}
Widget _buildAlertItem(AlertInfoBO alert) {
return Container(
margin: EdgeInsets.only(bottom: 12.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
Icons.warning_amber_rounded,
color: const Color(0xFFFF7D00),
size: 24.w,
),
SizedBox(width: 8.w),
Expanded(
child: Text(
alert.title,
style: TextStyle(
fontSize: 26.sp,
fontWeight: FontWeight.w500,
color: const Color(0xFFFF7D00),
),
),
),
],
),
SizedBox(height: 8.h),
Padding(
padding: EdgeInsets.only(left: 32.w),
child: Text(
alert.description,
style: TextStyle(
fontSize: 22.sp,
color: Colors.white70,
),
),
),
SizedBox(height: 8.h),
Padding(
padding: EdgeInsets.only(left: 32.w),
child: Text(
alert.time,
style: TextStyle(
fontSize: 20.sp,
color: Colors.white54,
),
),
),
],
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/models/bo/monitoring_bo.dart';
class MetricCard extends StatelessWidget {
final MonitoringMetricBO metric;
const MetricCard({
super.key,
required this.metric,
});
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(vertical: 20.h, horizontal: 16.w),
decoration: BoxDecoration(
color: Color(metric.backgroundColorValue),
borderRadius: BorderRadius.circular(20.r),
border: Border.all(
color: Color(metric.borderColorValue),
width: 1,
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
metric.value,
style: TextStyle(
fontSize: 48.sp,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
SizedBox(height: 8.h),
Text(
metric.unit,
style: TextStyle(
fontSize: 24.sp,
color: Colors.white70,
),
),
SizedBox(height: 16.h),
Text(
metric.label,
style: TextStyle(
fontSize: 22.sp,
color: Colors.white70,
),
),
],
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class MonitoringScreen extends StatelessWidget {
final VoidCallback? onRefresh;
final VoidCallback? onSnapshot;
final VoidCallback? onRecord;
const MonitoringScreen({
super.key,
this.onRefresh,
this.onSnapshot,
this.onRecord,
});
@override
Widget build(BuildContext context) {
return Container(
height: 420.h,
decoration: BoxDecoration(
gradient: const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0xCC63A0FF), Color(0xCC0024C4)],
),
borderRadius: BorderRadius.circular(20.r),
border: Border.all(color: Colors.white24, width: 1),
),
child: Stack(
children: [
Center(
child: Text(
'监控画面',
style: TextStyle(
fontSize: 40.sp,
color: Colors.white70,
fontWeight: FontWeight.w500,
),
),
),
Positioned(
bottom: 24.h,
right: 24.w,
child: Row(
children: [
_buildIconButton(Icons.refresh, onRefresh),
SizedBox(width: 16.w),
_buildIconButton(Icons.camera_alt, onSnapshot),
SizedBox(width: 16.w),
_buildIconButton(Icons.videocam, onRecord),
],
),
),
],
),
);
}
Widget _buildIconButton(IconData icon, VoidCallback? onPressed) {
return Container(
width: 60.w,
height: 60.w,
decoration: BoxDecoration(
color: const Color(0x331E10B6),
borderRadius: BorderRadius.circular(30.r),
border: Border.all(color: Colors.white24, width: 1),
),
child: IconButton(
icon: Icon(icon, color: Colors.white, size: 32.w),
onPressed: onPressed,
padding: EdgeInsets.zero,
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/models/bo/monitoring_bo.dart';
class PatientInfoCard extends StatelessWidget {
final PatientInfoBO patientInfo;
const PatientInfoCard({
super.key,
required this.patientInfo,
});
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(24.w),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFF1E10B6), Color(0xFF3A87FF)],
),
borderRadius: BorderRadius.circular(20.r),
border: Border.all(color: Colors.white24, width: 1),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(20.r),
child: Container(
width: 100.w,
height: 100.w,
decoration: BoxDecoration(
border: Border.all(color: Colors.white24, width: 1),
borderRadius: BorderRadius.circular(20.r),
),
child: patientInfo.avatarUrl.isEmpty
? Icon(Icons.pets, size: 56.w, color: Colors.white54)
: Image.network(
patientInfo.avatarUrl,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return Icon(
Icons.pets,
size: 56.w,
color: Colors.white54,
);
},
),
),
),
SizedBox(width: 24.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
patientInfo.name,
style: TextStyle(
fontSize: 32.sp,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
SizedBox(height: 12.h),
_buildInfoText(patientInfo.owner),
SizedBox(height: 8.h),
_buildInfoText(patientInfo.phone),
SizedBox(height: 8.h),
_buildInfoText(patientInfo.breed),
SizedBox(height: 8.h),
_buildInfoText(patientInfo.doctor),
],
),
),
],
),
);
}
Widget _buildInfoText(String text) {
return Text(
text,
style: TextStyle(
fontSize: 24.sp,
color: Colors.white70,
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/models/bo/monitoring_bo.dart';
class SidebarMenuItem extends StatelessWidget {
final MonitoringMenuItemBO item;
final VoidCallback? onTap;
const SidebarMenuItem({
super.key,
required this.item,
this.onTap,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Container(
padding: EdgeInsets.all(24.w),
decoration: BoxDecoration(
gradient: const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0xCC63A0FF), Color(0xCC0024C4)],
),
borderRadius: BorderRadius.circular(20.r),
border: Border.all(color: Colors.white24, width: 1),
),
child: Row(
children: [
Text(
item.icon,
style: TextStyle(fontSize: 40.w),
),
SizedBox(width: 16.w),
Expanded(
child: Text(
item.title,
style: TextStyle(
fontSize: 24.sp,
color: Colors.white,
fontWeight: FontWeight.w500,
),
),
),
],
),
),
);
}
}
......@@ -66,4 +66,4 @@ class LoginCubit extends Cubit<LoginState> {
void forgotPwd() {
// TODO: 跳转到忘记密码页面
}
}
\ No newline at end of file
}
......@@ -39,4 +39,4 @@ class LoginState extends Equatable {
savedUsername,
savedPassword,
];
}
\ No newline at end of file
}
......@@ -162,9 +162,8 @@ class LoginView extends StatelessWidget {
if (_frmGlobalKey.currentState!
.validate()) {
cubit.login(
username:
_txtUserNameController.text
.trim(),
username: _txtUserNameController.text
.trim(),
password:
_txtPwdController.text.trim(),
rememberPassword:
......@@ -189,4 +188,4 @@ class LoginView extends StatelessWidget {
),
);
}
}
\ No newline at end of file
}
......@@ -47,4 +47,4 @@ class BtnLogin extends StatelessWidget {
),
);
}
}
\ No newline at end of file
}
......@@ -26,4 +26,4 @@ class BtnReset extends StatelessWidget {
),
);
}
}
\ No newline at end of file
}
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class PasswordField extends StatefulWidget {
final TextEditingController controller;
......@@ -79,4 +78,4 @@ class _PasswordFieldState extends State<PasswordField> {
),
);
}
}
\ No newline at end of file
}
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class UsernameField extends StatelessWidget {
final TextEditingController controller;
......@@ -55,4 +55,4 @@ class UsernameField extends StatelessWidget {
),
);
}
}
\ No newline at end of file
}
......@@ -42,13 +42,13 @@ dependencies:
flutter_bloc: ^8.1.5
equatable: ^2.0.5
flutter_screenutil: ^5.9.3
fluttertoast: ^9.1.0
loading_animation_widget: ^1.3.0
# fl_chart: ^1.2.0
flutter_switch: ^0.3.2
fl_chart: ^0.71.0
infinite_scroll_pagination: ^5.1.1
logger: ^2.7.0
fluttertoast: ^9.1.0
# fl_chart: ^0.71.0
# fl_chart: ^1.1.0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment